Subject: Maintenance frame contention vs CONTINUATION

From: David Krauss <[email-masked]>
Date: Tue, 22 Apr 2014 07:16:22 +0800

One purpose of a small frame size, which led to CONTINUATION frames, is to ensure timely delivery of PRIORITY frames. (I would infer this applies, even more, to WINDOW_UPDATE.) But the CONTINUATION spec says they must form an uninterrupted chain after HEADERS, and that’s the same as just having one big frame.

Do header blocks displace non-content-bearing frames such as PRIORITY, WINDOW_UPDATE, RST_STREAM, PING, and SETTINGS, or is there supposed to be an exception to the rule?

---

From: Martin Thomson <[email-masked]>
Date: Mon, 21 Apr 2014 16:24:58 -0700

> Do header blocks displace non-content-bearing frames such as PRIORITY, WINDOW_UPDATE, RST_STREAM, PING, and SETTINGS, or is there supposed to be an exception to the rule?

Yes, header blocks clog the pipe.  No exceptions.

Note that header blocks aren't flow controlled, so it's the TCP
congestion window that becomes blocked, if anything.  Thus, the
primary consequence of a large header block is head of line blocking
for everything.

---

From: Roberto Peon <[email-masked]>
Date: Mon, 21 Apr 2014 16:49:36 -0700

On Mon, Apr 21, 2014 at 4:16 PM, David Krauss <[email-masked]> wrote:

> One purpose of a small frame size, which led to CONTINUATION frames, is to
> ensure timely delivery of PRIORITY frames. (I would infer this applies,
> even more, to WINDOW_UPDATE.) But the CONTINUATION spec says they must form
> an uninterrupted chain after HEADERS, and that’s the same as just having
> one big frame.
>

And by timely delivery, we all mean that the *execution* of priority
changes be timely :)
That could happen as a result of a new stream appearing at a higher
priority than a previously existing stream, and thus doesn't require a
priority frame.
-=R

>
> Do header blocks displace non-content-bearing frames such as PRIORITY,
> WINDOW_UPDATE, RST_STREAM, PING, and SETTINGS, or is there supposed to be
> an exception to the rule?
>
>
>

---

From: David Krauss <[email-masked]>
Date: Tue, 22 Apr 2014 11:17:34 +0800

WINDOW_UPDATE frames are the tricky part. Consider a multithreaded server with a scheduling algorithm arbitrating the network output stream. If the scheduler sends an incomplete header block, then the usually asynchronous processes of sending WINDOW_UPDATEs and responding to PINGs need to wait for it to finish.

The solution is to either schedule the entire block all at once, which perhaps imposes a size limit, or to be prepared for the priority inversion.

The upshot is that large header blocks will be handled poorly by some implementations (which isn’t really news), and protocols with large header blocks going one way and data going the other way may tend to self-throttle (which sounds like a minor corner case).

On 2014–04–22, at 7:49 AM, Roberto Peon <[email-masked]> wrote:

> And by timely delivery, we all mean that the *execution* of priority changes be timely :)
> That could happen as a result of a new stream appearing at a higher priority than a previously existing stream, and thus doesn't require a priority frame.

---

From: Martin Thomson <[email-masked]>
Date: Mon, 21 Apr 2014 21:13:18 -0700

> The solution is to either schedule the entire block all at once, which perhaps imposes a size limit, or to be prepared for the priority inversion.

Correct, though it's entirely possible that you can't dump the entire
block due to TCP window size constraints.

No one claimed we were making HTTP perfect here, but I think that you
will find that it's manageable with smaller sets of header fields.  If
you want real speed and occasionally need huge header blocks - and I
hesitate to suggest this - you may find that you can amortize the
effects by using multiple connections.  I wouldn't recommend that on
the big-I internet for general usage though.

---

From: Roberto Peon <[email-masked]>
Date: Mon, 21 Apr 2014 21:27:33 -0700

Definitely not recommended.

-=R

On Mon, Apr 21, 2014 at 9:13 PM, Martin Thomson <[email-masked]>wrote:

> > The solution is to either schedule the entire block all at once, which
> perhaps imposes a size limit, or to be prepared for the priority inversion.
>

---

From: David Krauss <[email-masked]>
Date: Tue, 22 Apr 2014 12:28:08 +0800

> block due to TCP window size constraints.

Various things break. The best strategy is to let the scheduler dictate an arbitrary upper limit, which might come from further down the network stack. After that, the client is stuck with priority inversion — it’s their fault anyway.

> will find that it's manageable with smaller sets of header fields.  

:) I’m just thinking in terms of limits that should be specified for my implementation. Right, there’s no problem, and “perfection” harming implementability would itself be a fault.