- From: Roy T. Fielding <fielding@gbiv.com>
- Date: Fri, 29 Aug 2014 15:49:58 -0700
- To: HTTP Working Group <ietf-http-wg@w3.org>
This comment is in reference to section 4.1 of http://tools.ietf.org/id/draft-ietf-httpbis-http2-14.txt > 4.1. Frame Format > > All frames begin with a fixed 9-octet header followed by a variable- > length payload. > > 0 1 2 3 > 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > | Length (24) | > +---------------+---------------+---------------+ > | Type (8) | Flags (8) | > +-+-+-----------+---------------+-------------------------------+ > |R| Stream Identifier (31) | > +=+=============================================================+ > | Frame Payload (0...) ... > +---------------------------------------------------------------+ > > Frame Layout I think this has become a bit moth-eaten over time as the WG has adjusted field lengths and perhaps added or removed a few. I also find the use of a bit array with magic gaps to be editorially bizarre, but this message is about the actual bits. I should be shocked that folks are "not concerned" about the use of a 9-octet header and the resulting effect on data alignment, but it is true that it won't matter much to character-oriented Web traffic. Nevertheless, I'd expect HTTP/2 to at least make an effort here given the number of APIs that don't process character traffic. Looking at the current spec, I think we can do better. 1) There are only 10 defined frame types and 2 useful flags. 2) The length is the most random of these fields and used last. 3) The stream identifier is the least random and used first. 4) Why are we reserving the high bit of an unsigned field? My suggestion is that the frame layout be changed to either 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Stream Identifier (32) | +---------------+-----------------------------------------------+ |Type(4)|Flag(4)| Payload Length (24) | +=+=============================================================+ | Frame Payload (0...) ... +---------------------------------------------------------------+ or 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Stream Identifier (32) | +---------------+-----------------------------------------------+ | Frame Type(8) | Payload Length (24) | +=+=============================================================+ | Frame Payload (0...) ... +---------------------------------------------------------------+ Rationale for both: 11% reduction in per-frame overhead A fixed 64bit layout is faster to parse than 72bits. A sender doesn't have to worry about 64bit alignment. A receiver is likely to partition based on stream id first. Rationale for A: If we need more than 6 additional frame types, we might as well skip to a new protocol version. If we need more than 4 flags per frame, we should use another type. The useful flags are END_STREAM and END_HEADERS and they could be defined in general (independent of frame type). Rationale for B: The current usage of frame flags in spec-14 is frightening. In all cases, they can and should be separate frame types. END_STREAM: Orthogonal. Could be moved to the reserved bit or made another frame type (an extra 8 bytes at end of stream is better than the extra 8 flag bits per frame). END_HEADERS: Orthogonal. Could be just another frame type or moved to the beginning of the frame payload in Headers, Continuation, and Push_Promise. PADDED: Padding is just a form of ignored data and should be a PADDING type. We can then remove those optional fields from the other frame types. Optional fields at the beginning of otherwise fixed frames is parser hell. Header PRIORITY: What do headers have to do with frame priority? Why here and not on DATA? We should instead have different frame types for MY_PRIORITY (this is how I am sending/reading) and YOUR_PRIORITY (this is how I want you to prioritize sending/reading). We can then remove those optional fields from the other frame types. Settings ACK: send an ACK frame type instead (and remove the additional complexity of processing requirements in the Settings type). Ping ACK: send a PONG type. Alternative A would just make the protocol more efficient and faster to parse at the cost of some extensibility. B would significantly simplify the protocol and the spec. Some combination of the two is also possible (e.g., 6 bits for type and 2 flag bits for END_STREAM and END_HEADERS). Alternatively, if END_STREAM is moved to the reserved bit E, then it would look like: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |E| Stream Identifier (31) | +---------------+-----------------------------------------------+ | Frame Type(8) | Payload Length (24) | +=+=============================================================+ | Frame Payload (0...) ... +---------------------------------------------------------------+ Yes, I know this suggestion comes late in the process. I was busy. Cheers, Roy T. Fielding <http://roy.gbiv.com/> Senior Principal Scientist, Adobe <http://www.adobe.com/>
Received on Friday, 29 August 2014 22:50:21 UTC