Skip to content

Conversation

@kazu-yamamoto
Copy link
Owner

kazu-yamamoto/http2#129 reported that a lot of very small window updates are sent.
This is due to the algorithm in maybeOpenRxWindow.

The algorithm delays the first window update until the available buffer size becomes greater than 1/2 of the total buffer size. But for the second window update or later, the small window update can be sent if the application consumes the available data slowly while new data are receiving.

@edsko first talked about the connection window. This makes sense to me because the connection window rapidly reaches the threshold before #4. @FinleyMcIlwaine showed that this can happens even for the stream window after #4.

My solution is simple. I would like to introduce the minimum size for window update whose default size is 1/8 of the total buffer.

@edsko
Copy link
Contributor

edsko commented Jul 12, 2024

@kazu-yamamoto I don't understand this fix. We start with a situation like this:

                rxfBufSize
       |------------------------|
-------------------------------------->
       ^                  ^     ^
  rxfConsumed             |  rxfLimit
                     rxfReceived
                          

                          |-----|
                         available    

where available < rxfBufSize / 2. We now shift the window:

                                  rxfBufSize
                          |------------------------|
---------------------------------------------------------------->
                          ^      ^                  ^
                          |      |            new  rxfLimit
                     rxfReceived |
                     rxfConsumed |
                             old limit
                          

                                 |------------------|
                                      winUpdate    

So

  • We know that available < rxfBufSize / 2, therefore
  • winUpdate > rxfBufSize / 2, which means that the check if
  • winUpdate > rfxBufSize / 8 must definitely be true.

@kazu-yamamoto
Copy link
Owner Author

@edsko In the case above, winUpdate is large.
So, this is not the case which we are trying to solve.

Consider another case where you saw a small value of window update with the cold code.
The old code announces it.
The new code delays the announce and waits for the timing of winUpdate > rfxBufSize / 8.

@edsko
Copy link
Contributor

edsko commented Jul 13, 2024

Sorry, I still don't understand :) Doesn't available < threshold already guarantee that the window update must be large? I guess I must be missing something :)

@kazu-yamamoto
Copy link
Owner Author

available < threshold guarantees that the first window update is delayed until the half of the received buffer is filled by peer. That's it. I does not guarantee that the next or later window updates are large.

After applying this patch, do you still see any window updates of small values?

@kazu-yamamoto
Copy link
Owner Author

Never mind. Probably you are right. I need to think this issue more.

@kazu-yamamoto
Copy link
Owner Author

@edsko First of all, please test this patch and check if your issue is fixed. I think this is a correct fix.

You assume that rxfConsumed is equal to rxfReceived in your second picture.
Such a case is very rare.
Many cases follow the example in the documentation.

--                 rxfBufSize
--        |------------------------|
-- -------------------------------------->
--        ^            ^           ^
--   rxfConsumed   rxfReceived  rxfLimit
--                     |01234567890|
--
-- In the case where the window update should be informed to the peer,
-- 'rxfConsumed' and 'rxfLimit' move to the right. The difference
-- of old and new 'rxfLimit' is window update:
--
--                   rxfBufSize
--          |------------------------|
-- -------------------------------------->
--          ^          ^             ^
--     rxfConsumed rxfReceived    rxfLimit
--                     |0123456789012| : window glows

winUpdate is the trailing "12" which can be small in old code.

@FinleyMcIlwaine
Copy link
Contributor

@kazu-yamamoto We have studied this PR again and we understand it better now. Perhaps it could be simplified if we base the decision to send a window update only on the amount of consumed data, and send a window update when we have consumed at least half of the window size (rather than 1/8th).

Either way, it is reducing the number of window updates. The simplification suggested above might just reduce them even further.

@kazu-yamamoto
Copy link
Owner Author

Thanks.
I will merge this and release a new version.
Please send me a PR when you find better parameters or an algorithm based on your operation!

@kazu-yamamoto kazu-yamamoto merged commit d1ba363 into main Jul 16, 2024
@kazu-yamamoto kazu-yamamoto deleted the min-size-for-window-update branch July 16, 2024 21:22
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Jan 30, 2025
## 0.1.4

* Using Integer instead of Int in LRUCache.

## 0.1.3

* Simplify `maybeOpenRxWindow` and improve docs
  [#7](kazu-yamamoto/network-control#7)

## 0.1.2

* introducing a minimum size for window update
  [#5](kazu-yamamoto/network-control#5)

## 0.1.1

* Change defaultMaxData
  [#4](kazu-yamamoto/network-control#4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants