Subject: Flow control protocol redundancy

From: David Krauss <[email-masked]>
Date: Sun, 23 Mar 2014 18:04:55 +0800

A connection and all its streams have independent flow control windows. All their initial window sizes are equal, and updated simultaneously by the SETTINGS frame. However, slack must be restored to each window independently by WINDOW_UPDATE frames.

Connection-wide WINDOW_UPDATE frames introduce redundancy and a potential source of protocol errors. Every byte represented by a stream WINDOW_UPDATE must also be accounted as a connection WINDOW_UPDATE before the slack can be used. Although stream updates contain sufficient information to maintain the connection-wide window, an endpoint must refrain from doing so.

Transmitting the connection WINDOW_UPDATE before that/those of the streams temporarily permits the remote side to transmit on streams with preexisting slack, i.e. whichever streams aren’t active. This potentially leads to priority inversion. Transmitting it after stream updates delays everything. Interleaving connection and stream updates wastes bandwidth.

Why not do away with connection-wide WINDOW_UPDATE frames? Let the stream updates affect the connection window in the same manner as data frames do (but negatively, and upon receipt rather than transmission).

The conceptual sacrifice is that it becomes impossible to define a flow-controlled frame type that is not associated with a stream. But this is currently meaningless, and it seems very reasonable as a future restriction too.

---
On a related note, I don’t see why a window size should ever be allowed to exceed the initial size. FIFO buffers usually have fixed size. Failing to set/update the initial window size renders a receiver incapable of attempting to throttle back connections that might have become overcommitted with expected data. Currently there are two different ways to increase the total window size, with slightly different consequences. Such a redundancy increases the range of remote behaviors to be tested against, and ultimately harms reliability.

---

From: David Krauss <[email-masked]>
Date: Mon, 24 Mar 2014 09:01:29 +0800

Now I find the thread "WINDOW_UPDATE with streamid = 0 redundant?” from Feb 11. Several arguments are made in this discussion, all flawed:

1. The connection-level window is not the sum of the stream-level windows. Nobody said it was. Absent connection-wide updates, the connection window would be the sum of all the stream-level changes (credits and debits) plus the initial size.

2. Streams may over-advertise their windows, then rely on connection-level updates to finalize the credit transfer. This does not provide any capability, and such practice means that some streams are being throttled, but other streams cannot be throttled until the excess credit is consumed.

3. Common practice is to allow window size to exceed INITIAL_WINDOW_SIZE. We’re in a prototyping phase, and bugs in prototypes do not constitute precedents.

4. A client may wish to accept a stream in a stalled state. The current flow control protocol does not allow this even with abuse. A sender always starts with credit equal to INITIAL_WINDOW_SIZE. Anyway, dependency and (re)-prioritization already provides for this, and with pushes (the mentioned use-case) dependency is the default. If prioritization isn’t working properly, perhaps that protocol needs to be extended.

5. The difference in stream credit may be used to manipulate a proxy. Flow control is a hop-to-hop protocol and it should not be used for end-to-end control. This is likely to pessimize proxy behavior, for example a change only propagates as fast as proxy buffers empty out. The end-to-end prioritization protocol is appropriate.

6. A small initial window is the way to effect 100 CONTINUE. If this is desired, then a small initial window should be the default. Why should the standard require reconfiguration at the low level of flow control to allow a server to support apps which might use the high-level CONTINUE construct? Everyone will be downsizing their windows. Of course there are other means to this end.

Also, I should mention that the idea of over-advertisement reeks of an integer overflow bug. Sloppy accounting leads to accumulated deficits. A server bug that is merely deferred for a long time will be extremely frustrating when it is finally triggered. The current standard seems to grant servers the right to fudge the accounting, but requires clients to abruptly terminate the connection when the “money supply” is exhausted.

In summary, multi-level flow control isn’t really flow control, but emulation of some other features. Since HTTP/2 already has those features, it is still redundant, and furthermore encourages avoidance of more appropriate practices.

P.S. Sorry for the earlier double post, mail client was acting up…