2026年3月26日(木) 14:07 Willy Tarreau <[email protected]>: > On Thu, Mar 26, 2026 at 03:19:49PM +1100, Martin Thomson wrote: > > On Wed, Mar 25, 2026, at 15:34, Kazuho Oku wrote: > > > Yes, using short TLS records during startup is important. In fact, > h2o > > > has long been doing that for HTTP/2. > > > > Definitely. Long TLS records leads to more latency, because more bytes > share fate. > > > > > I would argue, however, that when a QMux sender emits short TLS > > > records, it should also use correspondingly short framing units. > > > > This is where we start to diverge. TLS is the only layer at which > framing > > forces receivers to wait for bytes. At the QMux layer, you can receive > 10 > > bytes of a 1k record. Those 10 bytes are usable. Introducing record > framing > > *encourages* implementers to be lazy and wait for the whole record, but > > that's going to make their implementation more vulnerable to performance > > problems. > > I agree, but you and Kazuho are not speaking about the same thing. Your > (and my) concerns are that we don't needlessly complicate the protocol > with rules/constraints that are not strictly needed. Kazuho's concern is > that the sender of an large data frame doesn't stop sending in the middle > of that data frame, blocking the mux output and preventing any other higher > priority frame from being sent. > > This last point is exactly what H2 already has to deal with, and I would > say that it's purely implementation-specific. Some implementations might > very well want to send super large frames that are progressively split into > TLS recors that are decrypted by the receiver which progressively reads, > while others might prefer to produce more smaller frames (and possibly > smaller TLS records) to make sure never to leave the mux in a blocked > state. In haproxy with h2 for example we always make data frames that > can fit into the available buffers to make sure never to block any other > frame. But that's only a choice, as the mux also supports sending only a > partial frame (e.g. a large headers frame). >
Yes, implementations can use different strategies to avoid blocking. At the same time, I think MT is correct to point out that specifications guide developers to implement their stacks in specific ways. From that perspective, the QMux Record approach prioritizes minimizing divergence from existing QUIC stacks, and then, as a secondary goal, mitigates the effect of blocking by encouraging alignment between TLS record and QUIC frame boundaries. The alternative direction would be to optimize more aggressively against blocking, even if that means requiring all implementations to diverge more substantially from QUIC v1 decoding / processing behavior. IMO that would look like H3 frames that have no size limit and require incremental processing; see https://mailarchive.ietf.org/arch/msg/quic/K1vMcAoai0oVUr-r5UU_QBfmrwU/. At this point, I do not see a particularly attractive middle ground between these two directions. > Also in my opinion we shouldn't put too many TLS-based constraints because > TLS is one way to securely transport qmux and which happens to use records, > but for example UNIX stream sockets would not have such restrictions. And > by the way, H2 doesn't require to know the TLS record lengths either. > I agree that Unix sockets do not have the TLS property of delivering bytes that have been read but cannot yet be decrypted. Therefore, blocking becomes inevitable on Unix sockets, unless QMux receivers implement incremental processing of STREAM frames. That downside might be negligible considering the low latency and high bandwidth of Unix sockets. On the other hand, people have expressed interest in running QMux over message-oriented substrates such as RDMA or WebSockets. For such deployments, having a record layer that can be mapped more naturally onto the underlying substrate could be beneficial. So I think this is another trade-off, after all. > Just my two cents, > Willy > -- Kazuho Oku
