Subject: [quicwg/base-drafts] DATA frame encoding is inefficient for long dynamically generated bodies (#1885)

From: Ryan Hamilton <[email-masked]>
Date: Thu, 18 Oct 2018 16:06:12 -0700

In the common case of a long response body that is dynamically generated, it is not possible to know the full length up front. Instead, the body is often read in chucks from some backend/data source and written to the wire as it's available. Since response bodies need to be encoded in DATA frames with an explicit length this typically means splitting the body into numerous chunks. Instead if would be more efficient if we could set a length of "until end of stream" (encoded as 0 or some such) which would allow the sender to write a single DATA frame header and the simply send the entire body without additional framing.

HTTP/2 explicitly tries to avoid overly long frames. This is a feature for HTTP/2 in which the frames for multiple streams are sent on the same in-order sequence of bytes, so a long frame potentially introduces head of line blocking for other higher priority data. But for QUIC there is no such concern since these DATA frames are all within the same stream.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885

---

From: Lucas Pardue <[email-masked]>
Date: Thu, 18 Oct 2018 23:20:05 +0000 (UTC)

I'm sympathetic to the issue but not sure it needs fixing in v1. What is worse case overhead?

The proposal seems similar to some aspect of Roberto and Jeff's ideas. A slightly different type of stream could carry just a response, and permit simple random access of bytes across the entire stream.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431195623

---

From: Dmitri Tikhonov <[email-masked]>
Date: Thu, 18 Oct 2018 16:34:33 -0700

> Instead if would be more efficient if we could set a length of "until end of stream" (encoded as 0 or some such) which would allow the sender to write a single DATA frame header and the simply send the entire body without additional framing.

Yes, this would be nice.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431198090

---

From: ianswett <[email-masked]>
Date: Thu, 18 Oct 2018 18:36:44 -0700

I previously missed this potential issue, but I think it's worth fixing, because for cases like large content delivery(ie: video streaming, etc), this minimizes overhead, complexity, and makes it easy to provide a zero-copy API on both the send and receive sides.

Also, 0 length is currently disallowed in DATA, so we have a value available in the existing frame we can define as something useful if we'd like.

I expect if this was supported, >90% of HTTP DATA frames would use it, which speaks to the prevalence of this use cause.  Having to specify a length is in many ways a special case, and the typical case is "the rest of the QUIC stream is DATA".  The only two cases I can think of where that wouldn't be true are server push, which is rarely used, and trailers, which are rarely supported and even more rarely used.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431216984

---

From: Martin Thomson <[email-masked]>
Date: Thu, 18 Oct 2018 18:40:52 -0700

New feature!  Be prepared to take this to Bangkok and have it resolved there.  I think that we're close to saying "no" to these automatically.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431217675

---

From: ianswett <[email-masked]>
Date: Thu, 18 Oct 2018 18:48:14 -0700

To clarify, this is a minor change to an existing frame.

Also, not many people have implementation experience with the HTTP mapping, so we're going to hit some small issues like this as implementers catch up.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431218796

---

From: Martin Thomson <[email-masked]>
Date: Thu, 18 Oct 2018 18:49:44 -0700

I disagree.  It's a new capability.  I'm not saying that asking for a new capability is out of bounds, just warning you that the door is about to close.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431219045

---

From: Kazuho Oku <[email-masked]>
Date: Thu, 18 Oct 2018 18:50:44 -0700

@RyanAtGoogle 
> Instead if would be more efficient if we could set a length of "until end of stream" (encoded as 0 or some such) which would allow the sender to write a single DATA frame header and the simply send…

Doesn't having a "end of stream" signal as part of the frame payload mean that we would need to escape the contents of HTTP if it contains the octets that can be interpreted as the "end of stream" signal?

Assuming that my understanding is correct, this sounds like MIME multipart. I prefer current chunked encoding style above that, because you do not need to scan through the content that you'd be forwarding.

Or am I missing something?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431219227

---

From: Ryan Hamilton <[email-masked]>
Date: Fri, 19 Oct 2018 04:34:11 +0000 (UTC)

@kazuho the end of stream signal is the QUIC transport-level FIN. Thankfully, it does not need to be encoded at the HTTP layer. I think it's more like HTTP/1.1 "Connection: close" than MIME multipart.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431241978

---

From: Kazuho Oku <[email-masked]>
Date: Thu, 18 Oct 2018 21:49:02 -0700

@RyanAtGoogle I see. Thank you for the clarification.

So the premise for using the proposed method is that trailers are not going to be sent.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431243907

---

From: Lucas Pardue <[email-masked]>
Date: Fri, 19 Oct 2018 00:03:48 -0700

To generalise Ian's observation. This greedy DATA frame would prevent onward use of frame types on a stream. Not only the core frames like HEADERS and PUSH_PROMISE but also extension frames such as ALTSVC. 

I think server push is actually ok here because a server would probably want to send promises before the response body (to a avoid a race condition).

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431265527

---

From: Dmitri Tikhonov <[email-masked]>
Date: Fri, 19 Oct 2018 12:35:39 +0000 (UTC)

> I'm sympathetic to the issue but not sure it needs fixing in v1. What is worse case overhead?

When one transfers large files, the overhead incurred by the DATA frames will be on the order of 3 bytes for every `[ ~1 MSS, 2^14 - 1 ]` bytes of content, or between about 0.2% and 0.02%.

@ianswett writes:

> The only two cases I can think of where that wouldn't be true are server push, which is rarely used, and trailers, which are rarely supported and even more rarely used.

The server push will continue to be rarely used if the API makes its use inconvenient.  For example, one can imagine that a server may want to push after sending a few KB of data (a finite DATA frame) -- to parse the HTML for CSS links or what-not.  An implementation that only allows pushes before the first (and only) DATA frame will make using server push in such manner more difficult.  Because it is easier to support only a single DATA frame of indeterminate size, it is likely that many implementations will do just that.

The complexity associated with framing data into DATA frames is real (if you want to do it efficiently), but not insurmountable.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431348155

---

From: Lucas Pardue <[email-masked]>
Date: Fri, 19 Oct 2018 10:12:30 -0700

Thanks for saving me the effort of calculating that Dmitri. Given that this bit of HQ mirrors H2 the overhead is neutral in that perspective. I'm of the same opinion as Martin that this is a "new feature" that offers up to 0.2% bandwidth saving. What is the bar for new features.

(New because this it changes the semantics in comparison to H2).

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431433421

---

From: Mike Bishop <[email-masked]>
Date: Fri, 19 Oct 2018 17:59:38 +0000 (UTC)

I'm sympathetic to the desire to reduce framing overhead, and having previously described the frames as "regions," I'm not philosophically opposed to having a region run to the end of the stream.  However, we've built / inherited from H2 a model in which frames have a known length from the start (though some might be so large that you have to process them in a streaming fashion).  I'm cautious about up-ending that model and saying that some frames have indeterminate length, and you'll know the end when you get there.

Depending on your implementation model, that might be fine.  If you have a processor that gets fed the bytes until the end of the frame, then it already handles a stream and being told that the payload has ended after/as the last byte is written to it.  This is a scoped change to the layer that reads the bytes from the stream and stuffs them into the processor.  If you have a processor that gets told the length and consumes that many bytes from the stream, this might be more of an architectural change.

I'm curious to hear from implementers how much of a challenge they foresee this being in their architectures.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431447381

---

From: Mike Bishop <[email-masked]>
Date: Fri, 19 Oct 2018 18:12:17 +0000 (UTC)

Also, rather than making DATA "special," I'd probably just add text to the framing layer section that a length of zero means the frame extends to the end of the QUIC stream.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431451120

---

From: MikkelFJ <[email-masked]>
Date: Fri, 19 Oct 2018 18:32:13 +0000 (UTC)

Initially did not see much point in this, but if you are parsing text and generating output, it it is hard to decide on any reasonable chunk size as you discover the output as you go. You'd have to buffer data until you hae enough to create a frame. Being able to avoid that has value beyond saving 0.2%.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431456856

---

From: Dmitri Tikhonov <[email-masked]>
Date: Fri, 19 Oct 2018 11:35:36 -0700

> You'd have to buffer data until you have enough to create a frame. Being able to avoid that has value beyond saving 0.2%.

Yes, there is certainly complexity associated with writing out streaming data. Nevertheless, one should not *have to* buffer.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431457750

---

From: ianswett <[email-masked]>
Date: Fri, 19 Oct 2018 12:23:42 -0700

@MikeBishop gQUIC currently only has this model, because it doesn't use H2 DATA frames, and the implementation is very straightforward and easy to optimize so my perspective is switched from yours.  Given there's no code shared between H2 and HTTP over QUIC, I think it's a mistake to assume we have or should inherit the region model from H2.

To reiterate what @dtikhonov and @mikkelfj are saying, for me this is more about making fast implementations that minimize copies and allocations easier to implement, and less about minimizing framing overhead.  In my case, I believe I could never send a length and all existing use cases.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431471861

---

From: Lucas Pardue <[email-masked]>
Date: Fri, 19 Oct 2018 19:33:35 +0000 (UTC)

gQUIC also has a different way of achieving HTTP header transfer, which means it had HoL blocking :)

Things are just different in HQ, it's a chance do you wind some of the compromises that QUIC made. As an implementor I'd like to have an environment that creates new opportunity, just as much as performance.

The direction of conversation is positive, and I agree performance isn't just shaving bandwidth. Mike's idea creates a general approach that I like.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431474652

---

From: Dmitri Tikhonov <[email-masked]>
Date: Fri, 19 Oct 2018 12:48:49 -0700

One concern I have about adding the greedy DATA frame is that it may very well mean that no implementation will actually generate sized DATA frames:

> Because it is easier to support only a single DATA frame of indeterminate size, it is likely that many implementations will do just that.

Which, in turn, will mean that a large chunk of everyone's HQ code that reads DATA frames with sizes will go  unutilized.  The atrophy and death of a sized DATA frame -- perhaps in the next version of QUIC -- is the next logical step.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431478990

---

From: Kazuho Oku <[email-masked]>
Date: Fri, 19 Oct 2018 14:12:06 -0700

@dtikhonov As a developer of a HQ proxy capable of forwarding trailers, I can say that H2O/quicly will generate sized DATA frames.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431500344

---

From: Ryan Hamilton <[email-masked]>
Date: Fri, 19 Oct 2018 14:39:37 -0700

@MikeBishop Oh! I love the idea of generalizing this to all frames, not just data. This would be quite convenient for body-less requests/responses.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431506972

---

From: Kazuho Oku <[email-masked]>
Date: Fri, 19 Oct 2018 14:52:54 -0700

@MikeBishop 
> I'm curious to hear from implementers how much of a challenge they foresee this being in their architectures.

In case of H2O/quicly, it is almost nothing to support DATA frames expanding to EOS.

However, it is harder to do the same for other types of frames. The code is based on the assumption that we can cap the maximum size of the frames, and buffer them until they are fully received.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431510458

---

From: Lucas Pardue <[email-masked]>
Date: Fri, 19 Oct 2018 14:57:48 -0700

@RyanAtGoogle I had a similar thought but initially worried that EOS would kill the bidirectional stream too early. However I think I was wrong, because stream is closed from either direction.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431511638

---

From: Ryan Hamilton <[email-masked]>
Date: Fri, 19 Oct 2018 21:59:03 +0000 (UTC)

@kazuho how would this proposal prevent an implementation from capping the maximum size of a frame?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431511885

---

From: Mike Bishop <[email-masked]>
Date: Fri, 19 Oct 2018 14:59:09 -0700

@kazuho, for most of them, that's still true.  About half of frames have well-defined maximum sizes -- if you haven't hit EOS before that point, the frame is improperly formatted.  The frames whose payload is bounded only by the frame length field are DATA, HEADERS, PUSH_PROMISE, and (technically) SETTINGS.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431511906

---

From: Lucas Pardue <[email-masked]>
Date: Fri, 19 Oct 2018 15:05:39 -0700

Consider also extension frames like ORIGIN or CACHE_DIGEST (yes they don't exist, yes) that might be sent in the HQ control stream, those can't be EOS'd.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431513189

---

From: Kazuho Oku <[email-masked]>
Date: Fri, 19 Oct 2018 15:19:13 -0700

@RyanAtGoogle
> how would this proposal prevent an implementation from capping the maximum size of a frame?

It doesn't. However, introducing the concept of non-DATA frames terminated by EOS has a impact on complexity. We handle HQ frames in the following way:
* We keep the frame header in the receive buffer until all the header is delivered. Then,
* if it is a DATA frame, we pop the frame header from the receive buffer, and continue reading the data out from the receive buffer until we read the exact amount of data specified by the frame header
* if it is not a DATA frame, we check that the size of the frame is below 16KB. If it is above that, we issue a connection close. If it is below that, we keep the octets in the receive buffer until the entire frame arrives. Once the frame arrives, we process it in-place, then remove it from the receive buffer.

Having non-DATA frames terminated by EOS means that we need add a different path for the last bullet. I'm sure I can implement that, but my preference goes to avoiding it.

I can understand the motivation to use EOS as a terminator for DATA frames. It makes sense because you might emit a large number of DATA frames for each HTTP response, and because DATA is typically the last frame type to be sent using a stream. Neither of the two points apply to other frame types, which means that the optimization is far less useful for them, even though I understand the elegance of permitting that for all frame types.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431515701

---

From: Dmitri Tikhonov <[email-masked]>
Date: Sat, 20 Oct 2018 03:34:58 -0700

In our QPACK implementation, [ls-qpack](https://github.com/litespeedtech/ls-qpack), the decoder consumes header block as a stream.  Hence, having a header block of an unspecified size is no problem -- there is no buffering either way.

For QPACK encoder, it is a profitable optimization to be able to write some header blocks directly to the stream.  I share @RyanAtGoogle's emotions in this regard.

> Having non-DATA frames terminated by EOS means that we need add a different path for the last bullet. I'm sure I can implement that, but my preference goes to avoiding it.

Isn't this as simple as foregoing the initial size check and closing the connection if you do hit the internal limit?  Certainly, if you're willing to buffer 16KB - 1 bytes to process a frame, you should be willing to buffer 16KB -1 bytes and then throw them out and close the connection.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431568943

---

From: Dmitri Tikhonov <[email-masked]>
Date: Sat, 20 Oct 2018 03:48:36 -0700

@kazuho writes:
> As a developer of a HQ proxy capable of forwarding trailers, I can say that H2O/quicly will generate sized DATA frames.

What about larger players such as Google?  For example, because not many server implementations support server push and not many websites use it (and even fewer do it well), Google [floated the idea](https://github.com/httpwg/wg-materials/blob/gh-pages/ietf102/chrome_push.pdf) to "destroy" it.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431569753

---

From: Kazuho Oku <[email-masked]>
Date: Sat, 20 Oct 2018 03:55:37 -0700

@dtikhonov 
> Isn't this as simple as foregoing the initial size check and closing the connection if you do hit the internal limit?

You also need to handle EOS differently. In the bounded frame case, seeing EOS before consuming the entire frame is a protocol error. In the non-bounded case, seeing it is a non-error.

To generalize, allowing the use of EOS as a terminator for non-DATA frames introduces new complexity to *some* decoders. OTOH, allowing that does not simplify on the encoder side, because you need the code to emit such frames in the middle of the stream.

This is very different from DATA frames:
* For many HQ stacks, DATA would be the last frame to be emitted on a stream. Therefore, you can get rid of the code that emits bounded DATA frames if we introduce the use of EOS as a terminator.
* It does not make the decoder complex, because in practice no decoder will block until it receives an entire DATA frame.
* DATA will be the most frequently used frame (compared to nothing else). Therefore, it is beneficial to reduce the number of the frames (by allowing use of EOS as the terminator).

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431570158

---

From: Kazuho Oku <[email-masked]>
Date: Sat, 20 Oct 2018 03:58:24 -0700

@dtikhonov 
> What about larger players such as Google?

I hope that the developers will notice interoperability with the websites hosted by Fastly before shipping stacks with broken trailer handling :-)

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431570332

---

From: ianswett <[email-masked]>
Date: Sun, 21 Oct 2018 10:08:37 -0700

Curious: What do you use trailers for?

Clearly our code will end up having to support specified lengths due to interop and the small number of cases(push and trailers included) that we support.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431686042

---

From: Kazuho Oku <[email-masked]>
Date: Sun, 21 Oct 2018 14:55:08 -0700

@ianswett H2O is capable of sending server-timing headers as trailers.

However, regardless of the use case, any proxy (including edge servers) that can forward trailers need to use length-delimited DATA frames when forwarding a chunked response, because it cannot tell whether trailers exist until receiving all the response body.

> Clearly our code will end up having to support specified lengths due to interop and the small number of cases(push and trailers included) that we support.

Agreed. This discussion is not about simplifying the decoder. It's about simplifying the encoder used by certain endpoints (as well as reducing the network overhead in a small degree).

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431707592

---

From: Lucas Pardue <[email-masked]>
Date: Sun, 21 Oct 2018 15:53:20 -0700

This is a good observation. There is some industry attention being paid to chunking end-to-end through the delivery chain.

Perhaps there's scope for an extension to HQ and/or H2 that can explicitly declare no trailers on a stream, wresting performance on the endcode or pass through cases.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431711196

---

From: Martin Thomson <[email-masked]>
Date: Sun, 21 Oct 2018 17:06:24 -0700

> Also, rather than making DATA "special," I'd probably just add text to the framing layer section that a length of zero means the frame extends to the end of the QUIC stream.

@MikeBishop, how about allowing the frame to run past the end of the stream?  If you are sending less than 2^62-1, then the special case is that you read until `min(end_of_frame, end_of_stream)` and don't treat overflow as an error.  It's not completely without framing, but the framing goes right down (1.95e-18% I think).

(I say this, while not being all that receptive to the feature with so little benefit.)

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431715821

---

From: Kazuho Oku <[email-masked]>
Date: Sun, 21 Oct 2018 17:59:40 -0700

@LPardue 
> There is some industry attention being paid to chunking end-to-end through the delivery chain.

I understand the same way.

> Perhaps there's scope for an extension to HQ and/or H2 that can explicitly declare no trailers on a stream, wresting performance on the endcode or pass through cases.

I am not sure if I like the complexity, partly because the small performance gain we will see (see @dtikhonov' comment at https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431348155), and also because it could be hard to use; it is often the case that a proxy cannot guess at the time of connection establishment to which origin server it would be connecting (consider the use of secondary server certificates).

I think my preference might goes to fixing the issue in QUIC v2. For example, we could move the chunking layer into the transport. In addition to EOS, we could have a END_OF_BLOCK flag associated to a STREAM frame that indicates the end of each block within a STREAM.

Assuming that many of the application protocols will transfer size-delimited blocks (e.g. HQ frames), it would make sense to support the concept in transport.

Having it expressed as a flag of a STREAMS frame (by burning the frame type octet) will give us simplicity _and_ efficiency in terms of bandwidth, because we can totally omit the Length field of the HQ frames.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431719488

---

From: Kazuho Oku <[email-masked]>
Date: Sun, 21 Oct 2018 17:59:52 -0700

@LPardue 

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431719511

---

From: Kazuho Oku <[email-masked]>
Date: Sun, 21 Oct 2018 18:02:12 -0700

@LPardue 

> Perhaps there's scope for an extension to HQ and/or H2 that can explicitly declare no trailers on a stream, wresting performance on the endcode or pass through cases.

I am not sure if I like the complexity, partly because of the small performance gain we will see (see @dtikhonov' comment at https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431348155), and also because it could be hard to use; it is often the case that a proxy cannot guess at the time of connection establishment to which origin server it would be connecting (consider the use of secondary server certificates).

I think my preference might go to fixing the issue in QUIC v2. For example, we could move the chunking layer into the transport by adding a END_OF_BLOCK flag to a STREAM frame for indicating the end of each block within a STREAM. Assuming that many of the application protocols will transfer size-delimited blocks (e.g. HQ frames), it makes sense to support the concept in transport.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431719835

---

From: Kazuho Oku <[email-masked]>
Date: Sun, 21 Oct 2018 18:07:35 -0700

@LPardue 

Actually, my preference might go to fixing the issue in QUIC v2. For example, we could move the chunking layer into the transport by adding a END_OF_BLOCK flag to a STREAM frame for indicating the end of each block within a STREAM. Assuming that many of the application protocols will transfer size-delimited blocks (e.g. HQ frames), it makes sense to support the concept in transport.

Having it expressed as a flag of a STREAMS frame (by burning the frame type octet) will give us simplicity _and_ efficiency in terms of bandwidth, because we can totally eliminate the Length field of the HQ frames.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431720220

---

From: Mike Bishop <[email-masked]>
Date: Mon, 22 Oct 2018 09:11:57 -0700

Technically, don't you have to declare in your header whether there will be trailers and what they will be?  So that is actually known if you're parsing the HTTP semantic layer.  However, this layer of the mapping doesn't attempt to encode it.

@martinthomson, that's another way to do it, but it makes me very nervous to say that we can't tell the difference between intent and a bug.  Seems like a door to a security risk or at least potential consistency concerns.  Consider a proxy whose back-end connection is interrupted and closes the stream before the entire payload has been transferred -- that error gets propagated and looks like a normal, intended response under those rules.

(Of course, if the proxy wrote a zero length and then had that happen, the same issue would exist.)

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431882189

---

From: MikkelFJ <[email-masked]>
Date: Mon, 22 Oct 2018 16:20:29 +0000 (UTC)

Certainly taking the minimum of stream and frame seems like an invitation to problems.
Predeclaring trailers is inconvenient if you don't know that ahead of time. Separate stream, v2?

I (kind of) like what @kazuho wrote about blocks/boundaries within a stream in v2, but this is a large topic that digs into partial reliability. I'm not sure boundaries on their own are that useful because a flag in a stream header still require a stream frame while an application embedding its own framing can be more dense, depending on the frame size vs. packet size. I did make such a proposal a boundary proposal a long time ago (out of scope for v1).

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431884806

---

From: MikkelFJ <[email-masked]>
Date: Mon, 22 Oct 2018 16:25:03 +0000 (UTC)

Are there any technical issues with placing DATA frames in its own stream, like ordering dependencie or undue receiver complexity? Otherwise it seems like a cleaner solution than hacking a 0 length for some frames. I agree with @kazuho that magic 0 for all frames just complicates frame handling in general.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431886267

---

From: Lucas Pardue <[email-masked]>
Date: Mon, 22 Oct 2018 10:28:12 -0700

@MikeBishop perhaps, the current specs about Transfer Encoding and use of the "Trailer" header have caught me out in the past - I'm not aware of people using TE in H2 or HQ since chunked is forbidden.

As you hint toward, my point was to expose some information about the framing flow on streams explicitly on the stream, if they deviate from the standard behaviour. Such a signal could be generated by an origin and used by other endpoints to determine their behaviour. If this was at the mapping layer, it could avoid the need to invoke QPACK. Although, there may be legitimate reasons to decode QPACk anyway.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431905899

---

From: Mike Bishop <[email-masked]>
Date: Mon, 22 Oct 2018 17:44:33 +0000 (UTC)

@mikkelfj, yes.  That was the design adopted first by GQUIC then (in a different incarnation) in early versions of the HQ draft.  There needs to be a guaranteed ordering between parts of the response and PUSH_PROMISE frames, and QUIC only provides guaranteed ordering on the same stream.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-431911396

---

From: Kazuho Oku <[email-masked]>
Date: Mon, 22 Oct 2018 14:49:52 -0700

@MikeBishop 
> Technically, don't you have to declare in your header whether there will be trailers and what they will be? So that is actually known if you're parsing the HTTP semantic layer. However, this layer…

The use of `Trailers` header field is merely a recommendation (i.e. `SHOULD`). And as you point out, there is no signal at the encoding layer. So from an intermediary's perspective, IMO it's just more natural to forward the trailers as they are, regardless of what the value of (or the existence of) the Trailers header is. Though I agree that dropping trailers in case of the absence of the `Trailers` header field will not cause interoperability in practice.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-432002183

---

From: Kazuho Oku <[email-masked]>
Date: Mon, 22 Oct 2018 15:10:01 -0700

@mikkelfj 
> I (kind of) like what @kazuho wrote about blocks/boundaries within a stream in v2, but this is a large topic that digs into partial reliability. I'm not sure boundaries on their own are that useful because a flag in a stream header still require a stream frame while an application embedding its own framing can be more dense, depending on the frame size vs. packet size.

Well, it's a matter of how you encode it. We can for example define the encoding of STREAM frame as a series of blocks. That way, we can eliminate having needless metadata (i.e. stream ID, offset) for each block.

> I did make such a proposal a boundary proposal a long time ago (out of scope for v1).

Yeah. While I think that is the ideal thing to do, I do not want to revisit the discussion now. My intention is to use it as a counter-approach to express my impression that occasionally using EOS as a terminator of DATA frame is kind of a band-aid solution. Admittedly, this is a nice-looking band aid. But it is not ideal, and I'd prefer either applying it minimally or deferring it to v2 to fix the issue in the ideal way.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1885#issuecomment-432008505