-
Notifications
You must be signed in to change notification settings - Fork 25
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
Patch writePump performance hit #613
Patch writePump performance hit #613
Conversation
Looks like this block of code in writePump was using the nil after reseting the encoder, but it wasn't accomplishing anything with that call ```go encoder.ResetBytes(&frameContents) writeError = encoder.Encode(envelope.request.Message) encoder.ResetBytes(nil) // Upto v1.2.3 it did nothing, v1.2.4 and newer causes a panic ``` Actually, looking through ugorji's codec releases, it looks like this wouldn't have done anything upto v1.2.3 ```go // v1.2.3 and older `encoder.ResetBytes(nil)` does nothing // ResetBytes resets the Encoder with a new destination output []byte. func (e *Encoder) ResetBytes(out *[]byte) { if out == nil { return } var in []byte = *out if in == nil { in = make([]byte, defEncByteBufSize) } e.bytes = true e.wb.reset(in, out) e.resetCommon() } ``` Releases v1.2.4 and newer would have started the panic scenario ```go // v1.2.4 causes writepump panic with `encoder.ResetBytes(nil)` // ResetBytes resets the Encoder with a new destination output []byte. func (e *Encoder) ResetBytes(out *[]byte) { var in []byte = *out if in == nil { in = make([]byte, defEncByteBufSize) } e.bytes = true e.wb.reset(in, out) e.resetCommon() } ``` ```go // v1.2.5 and newer causes writepump panic with `encoder.ResetBytes(nil)` // ResetBytes resets the Encoder with a new destination output []byte. func (e *Encoder) ResetBytes(out *[]byte) { e.bytes = true e.wb.reset(encInBytes(out), out) e.resetCommon() } ``` What change in the ugorji/go/codec `ResetBytes` is that `out` buffers can no longer be nil's. Specifically, `encoder.ResetBytes(nil)` will kick off a panic due to an eventual nil dereferencing caused by ugorji's [`codec's encInBytes`](https://github.com/ugorji/go/blob/b4c725930670fc2d46721b17f4d6974c66fb50c1/codec/encode.go#L1451-L1452) receiving `out` as a nil. ```go func encInBytes(out *[]byte) (in []byte) { in = *out if in == nil { in = make([]byte, defEncByteBufSize) } return } ``` The solution is to revert the code and remove `encoder.ResetBytes(nil)` since it never did anything.
Codecov Report
@@ Coverage Diff @@
## main #613 +/- ##
==========================================
- Coverage 82.68% 82.59% -0.10%
==========================================
Files 184 184
Lines 10338 10340 +2
==========================================
- Hits 8548 8540 -8
- Misses 1580 1591 +11
+ Partials 210 209 -1
Flags with carried forward coverage won't be shown. Click here to find out more.
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
Kudos, SonarCloud Quality Gate passed! |
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.
Thanks for getting this done and researching so thoroughly!
Kudos, SonarCloud Quality Gate passed! |
Kudos, SonarCloud Quality Gate passed! |
@johnabass asked me to look into patching the performance hit after patching the writePump panic caused by the same encoder in #595
Looks like this block of code in writePump was using the nil after reseting the encoder, but it wasn't accomplishing anything with that call. The expected behavior was that a nil would reset the buffer to an empty []byte.
Actually, looking through ugorji's codec releases, it looks like this wouldn't have done anything upto v1.2.3
Releases v1.2.4 and newer would have started the panic scenario
What change in the ugorji/go/codec
ResetBytes
is thatout
buffers can no longer be nil's. Specifically,encoder.ResetBytes(nil)
will kick off a panic due to an eventual nil dereferencing caused by ugorji'scodec's encInBytes
receivingout
as a nil.The solution is to revert the code and replace
encoder.ResetBytes(nil)
withencoder.ResetBytes(&emptyBuffer)
.How To Test For writePump Panic
Ran the simulator & talaria locally or in one of dev/cd envs
Tested the patch with the following: