Subject: http2 Working Code

From: Greg Wilkins <[email-masked]>
Date: Fri, 13 Jun 2014 14:42:11 +0200

So Jetty's had a working http2 implementation for less that 48 hours and
I'm already feeling the affect of working code in as much as some of my
vocal opposition to some hpack/http2 design is melting away.    When asked
"should we make a provision for optionally flow controlling headers?", my
response was - nah it is too difficult to do without radical change, so
we'll just have to reject connections that send big headers.

However, I'm not100% sure if my acceptance is really for good technical
reasons, or just because of some kind of Stockholm syndrome.    But anyway,
for those that +1'd some of my recent criticisms, here an explanation of
why I've capitulated :)

When you see hpack at work it is pretty good.  The huffman is ok, with a
50% saving on average, but the differential headers does produce great
savings and you can see whole new requests pop out of header frames that
are only a few bytes long, even empty header frames. Plus it is kind of fun
to play with different encoding strategies.

I still don't like the whack-a-mole changing indexes and the need to copy
static entries.  But once implemented it does not feel too bad and the fact
that it prevents some encoding optimisations is not a huge deal as you do
get huge gains by just having common headers in the ref set.

Once you accept that the big gains are to be had by differential encoding,
then you are accepting a shared state table between streams.  The moment
you have that, then either you have to limit header sizes to a single frame
OR exclude headers from flow control - because it is just too difficult to
allow headers to block partially sent with the current style of shared
header table; OR have multiple share tables of some kind.

As the decision was made some time ago to have a single shared state table,
then the best approach is as Martin has said, to just treat Continuations
as part of one big uber-frame and hope that nobody important sends headers
so big that you have to reject them.

Note also that I do accept the requirement that we do need good compression
of headers, as it is good to pack in 80+ requests into a single slow start
window.  While this does kind of duplicate the solution of push, because if
push works, then there is no need to have 80+ requests do a round trip
before data can be sent.   But I guess there will always be deployment
modes where a single response from one server can provoke 80+ simultaneous
requests on a CDN - so both mechanisms are called for.

So working code has made me join the lets-suck-it-and-see camp.   Almost
all of the technical uglies do logically flow from the decision to have a
single shared state table (and the ones that don't are not huge
problems).      I believe that if this protocol is not found to be
acceptable by wider review/usage, then we will have to rewind all the way
back to considering multiple shared state tables or similar to avoid ending
up at the same place.

cheers

-- 
Greg Wilkins <[email-masked]>
http://eclipse.org/jetty HTTP, SPDY, Websocket server and client that scales
http://www.webtide.com  advice and support for jetty and cometd.

---

From: Willy Tarreau <[email-masked]>
Date: Fri, 13 Jun 2014 14:54:35 +0200

Hi Greg,

> back to considering multiple shared state tables or similar to avoid ending

Thanks for your positive feedback. I'm feeling slightly less scared by the
idea of trying to stuff it into haproxy during the upcoming weeks after 1.5
is released... But still scared anyway :-)

Willy

---

From: Mark Nottingham <[email-masked]>
Date: Fri, 13 Jun 2014 10:27:14 -0400

On 13 Jun 2014, at 8:42 am, Greg Wilkins <[email-masked]> wrote:

> 
> So Jetty's had a working http2 implementation for less that 48 hours and I'm already feeling the affect of working code in as much as some of my vocal opposition to some hpack/http2 design is melting away.    When asked "should we make a provision for optionally flow controlling headers?", my response was - nah it is too difficult to do without radical change, so we'll just have to reject connections that send big headers.
> 
> However, I'm not100% sure if my acceptance is really for good technical reasons, or just because of some kind of Stockholm syndrome.

Welcome :)

>    But anyway, for those that +1'd some of my recent criticisms, here an explanation of why I've capitulated :)
> 
> When you see hpack at work it is pretty good.  The huffman is ok, with a 50% saving on average, but the differential headers does produce great savings and you can see whole new requests pop out of header frames that are only a few bytes long, even empty header frames. Plus it is kind of fun to play with different encoding strategies.
> 
> I still don't like the whack-a-mole changing indexes and the need to copy static entries.  But once implemented it does not feel too bad and the fact that it prevents some encoding optimisations is not a huge deal as you do get huge gains by just having common headers in the ref set.
> 
> Once you accept that the big gains are to be had by differential encoding, then you are accepting a shared state table between streams.  The moment you have that, then either you have to limit header sizes to a single frame OR exclude headers from flow control - because it is just too difficult to allow headers to block partially sent with the current style of shared header table; OR have multiple share tables of some kind.
> 
> As the decision was made some time ago to have a single shared state table, then the best approach is as Martin has said, to just treat Continuations as part of one big uber-frame and hope that nobody important sends headers so big that you have to reject them.
> 
> Note also that I do accept the requirement that we do need good compression of headers, as it is good to pack in 80+ requests into a single slow start window.  While this does kind of duplicate the solution of push, because if push works, then there is no need to have 80+ requests do a round trip before data can be sent.   But I guess there will always be deployment modes where a single response from one server can provoke 80+ simultaneous requests on a CDN - so both mechanisms are called for.
> 
> So working code has made me join the lets-suck-it-and-see camp.   Almost all of the technical uglies do logically flow from the decision to have a single shared state table (and the ones that don't are not huge problems).      I believe that if this protocol is not found to be acceptable by wider review/usage, then we will have to rewind all the way back to considering multiple shared state tables or similar to avoid ending up at the same place.

Thanks for the feedback.

I think people would be interested in your thoughts on priority dependencies too, if you’re able...

Cheers,

P.S. Now that you’re here, my argument for a .au meeting is getting stronger...

Mark Nottingham   http://www.mnot.net/

---

From: Martin Thomson <[email-masked]>
Date: Fri, 13 Jun 2014 10:12:10 -0700

On 13 June 2014 05:42, Greg Wilkins <[email-masked]> wrote:
> I'm not100% sure if my acceptance is really for good technical reasons, or
> just because of some kind of Stockholm syndrome.

That remains a persistent concern for me.  It's easy to get so close
to something that you lose sight of how ugly it really is.

Thanks for the fedback.

---

From: Matthew Kerwin <[email-masked]>
Date: Sat, 14 Jun 2014 07:26:13 +1000

On 13 June 2014 22:42, Greg Wilkins <[email-masked]> wrote:

> reasons, or just because of some kind of Stockholm syndrome.
>

​
​For what it's worth, even without a fully implemented HTTP stack, once my
experimental HPACK+Huffman code was written and verified to at least
theoretically interop [1], all the implementation pain sort of evaporated,
so I'm in pretty much the same boat as Greg.

HPACK felt painful to implement, but - at least in my case - it wasn't
actually hard. And libraries are starting to become available, so the pain
can be avoided if you don't mind flirting with a potential future
monoculture.

[1] it correctly parsed stories from
https://github.com/http2jp/hpack-test-case/
​

-- 
  Matthew Kerwin
  http://matthew.kerwin.net.au/

---

From: David Krauss <[email-masked]>
Date: Sat, 14 Jun 2014 08:44:17 +0800

> When you see hpack at work it is pretty good.  The huffman is ok, with a 50% saving on average, but the differential headers does produce great savings and you can see whole new requests pop out of…

Huffman can only do 50% when the input is restricted to the characters 0, 1, and 2. Caching/differential encoding is where most of the savings currently comes from. The Huffman code saves 29% on its original corpus, which is composed mainly of lowercase words and numbers. Doing better than that should be highly unusual.

Anyway, congratulations!