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
Introduce an API that lets the user get the current datagram size #4294
base: master
Are you sure you want to change the base?
Conversation
I'm having trouble generating mocks using the latest https://github.com/uber-go/mock: running -// PackerAppendPacketCall wrap *gomock.Call
-type PackerAppendPacketCall struct {
+// MockPackerAppendPacketCall wrap *gomock.Call
+type MockPackerAppendPacketCall struct {
*gomock.Call
} which breaks lots of other code. Is this expected, and the other code using current names should be adjusted to use new names with |
You should only need to run |
6ec6b7d
to
48bc3df
Compare
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## master #4294 +/- ##
==========================================
- Coverage 84.17% 84.01% -0.15%
==========================================
Files 149 150 +1
Lines 15397 15450 +53
==========================================
+ Hits 12959 12980 +21
- Misses 1939 1967 +28
- Partials 499 503 +4 ☔ View full report in Codecov by Sentry. |
maxDatagramDataSize := (&wire.DatagramFrame{DataLenPresent: true}).MaxDataLen(maxDatagramFrameSize, s.version) | ||
|
||
s.connStateMutex.Lock() | ||
s.connState.MaxDatagramSize = int(maxDatagramDataSize) |
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.
Have we consider using atomic uint32?
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 convinced focusing on this is worthwhile right now. There are more important things to address first (which would likely affect whatever performance impact of updateMaxDatagramDataSize has), and if connStateMutex contention turns out to be a problem in the end, I think we might want to revisit how all of ConnectionState is accessed, not just this field.
connection.go
Outdated
@@ -527,6 +527,8 @@ runLoop: | |||
default: | |||
} | |||
|
|||
s.updateMaxDatagramDataSize() |
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.
Can we be smarter than running this once per runLoop
iteration? This is the hot path.
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.
Do you mean this should be moved to the end of runLoop
body? I wasn't sure under which conditions end of the runLoop
body is or isn't reachable.
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.
Not really. runLoop
iterates once per (batch of) packets received and sent. Which is a lot on an active QUIC connection.
The available space in the packet however only changes under 2 conditions (I think):
- When we update the connection ID.
- When we discover a new MTU.
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 there's another reason: encoded packet number length increases, which IIUC grows with RTT and how fast we send packets (as in, packets per unit of time.)
I also just realized I misread and misunderstood your initial comment, oops.
The simplest way I can think of would be just to rate limit updateMaxDatagramSize
. A more "precise" solution I can think of would be to run it in response to the 3 events that can change the available space: connection ID changed, PMTU changed, packet number length changed. Packet number length can change after every packet we send and on every ACK we receive. This reasoning is in fact why I initially went with running updateMaxDatagramSize
every runLoop
, as it runs in response to all of these events. In any case, do you think just rate limiting so that updateMaxDatagramSize
runs once in a while, e.g. every 10 ms or every N iterations of runLoop, would be good enough solution, or should we instead try to run updateMaxDatagramSize
in response to 3 events listed above? If we go with "every once in a while" solution, the users could be advised to underutilize the available space by 1-2 bytes to allow for growth if they start sending datagrams after a period of inactivity. We could also trigger updateMaxDatagramSize
in response to discarding datagrams when sending.
// | ||
// MaxDatagramSize is zero if datagrams are not supported on this | ||
// connection. | ||
MaxDatagramSize int |
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.
uint16?
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 don't mind making it uint16
, but I don't see what improvement this would have. At worst I believe this would, in some cases, cause the users to perform additional conversion in their code, as dealing with sizes of things that fit in core in Go conventionally is done in ints.
30dfde0
to
c037a37
Compare
c037a37
to
3d7ebd4
Compare
cc @marten-seemann @chungthuang @joliveirinha @tanghaowillow