-
-
Notifications
You must be signed in to change notification settings - Fork 300
Implement server::Builder::max_send_buffer_size #577
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I tried using |
f7d388f
to
4693e9c
Compare
@seanmonstar Do you think h2 should have a default maximum? |
Also, do you have any idea how I could write a test for this? |
4693e9c
to
30a66ec
Compare
@@ -175,6 +189,8 @@ impl Prioritize { | |||
self.try_assign_capacity(stream); | |||
} | |||
|
|||
self.current_send_buffer_size += sz as usize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used to do this prior to calling try_assign_capacity
. AFAIU that was wrong, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds right. The connection-level and stream-level should be updated together, but since updating the stream-level may make it exceed it's requested capacity and thus needs to check for more capacity, that must happen in-between.
A code comment about the ordering being important may be prudent.
Hm, probably yes. Also, it might be good (once we have it working) to compare how this change affects hyper's http2 |
@@ -736,6 +765,8 @@ impl Prioritize { | |||
tracing::trace_span!("updating stream flow").in_scope(|| { | |||
stream.send_flow.send_data(len); | |||
|
|||
self.current_send_buffer_size -= len as usize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this area needs to potentially wake up any tasks that have been waiting on "capacity", since now there is "more buffer space to use". The reason it needs to be done here, is because with flow control capacity, the connection doesn't actually get more until the peer has sent another WINDOW_UPDATE frame. So recv_window_update
will notify a task there. But buffer size isn't affected by WINDOW_UPDATE frames.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand. Why do we even call self.flow.assign_capacity(len);
below that line, if we are actually supposed to wait for the peer to send another WINDOW_UPDATE frame?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am even more confused that we call self.flow.send_data(len);
immediately afterwards we called self.flow.assign_capacity(len);
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't that mean that self.flow.available
never changes from Prioritize::pop_frame
? I don't understand the logic there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I called assign_connection_capacity
from poll_complete
after the reclaim_frame
call.
30a66ec
to
d837e1f
Compare
d837e1f
to
acb0041
Compare
tests/h2-tests/tests/flow_control.rs
Outdated
|
||
for _ in 0..3 { | ||
stream.reserve_capacity(5); | ||
stream = util::wait_for_capacity(stream, 5).await; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test is hanging there, and by the time h2 returns Poll::Pending
, Actions::task
is None
so there is no way to wake up the connection task to call poll_complete
from there.
t2.await.expect("srv body spawn"); | ||
t1.await.expect("srv body spawn"); | ||
t0.await.expect("srv end"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK the test is still wrong. We await for t2
before we await for t0
, so t0
is pending and nothing will wake it up when t2
notifies the connection task that it has frames to send, so the send buffer size never decreases and everything gets stuck.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind I misread. That being said, the test really doesn't help much finding where the issue with my patch is :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
h2/tests/h2-support/src/util.rs
Lines 56 to 66 in 2c53d60
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | |
let _ = ready!(self.stream().poll_capacity(cx)).unwrap(); | |
let act = self.stream().capacity(); | |
if act >= self.target { | |
return Poll::Ready(self.stream.take().unwrap().into()); | |
} | |
Poll::Pending | |
} |
There, poll_capacity
returns Ready(Some(0))
, and capacity
returns 0
, so act >= self.target
is false
, and Poll::Pending
gets returned even though nothing has been set up to wake up the task.
What do you think is wrong here? That poll_capacity
returns Ready(Some(0))
, or that wait_for_capacity
is badly conceived, or both?
No description provided.