Repository navigation
Decode numbers from a reader whose buffer is smaller than them - #54
Merged
Merged
Conversation
takeInt guarded Reader.takeInt with a check that the reader's buffer can hold the integer, because on a miss takeInt rebases, which asserts that. So a streaming reader with a buffer under 8 bytes failed every u64 or f64 with ReaderBufferTooSmall, even though nothing needs those bytes to be buffered together. Read the integer straight from the buffer when it is all there, and copy it out with readSliceAll otherwise, which works across refills. ReaderBufferTooSmall is now only returned for strings that have to be buffered whole, such as struct field names.
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 30 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
takeIntchecked that the reader's buffer could hold the integer before callingReader.takeInt. On a miss,Reader.takeIntrebases, and rebasing asserts that the bytes fit in the buffer. As a result, a streaming reader with a buffer under 8 bytes failed everyu64orf64withReaderBufferTooSmall, even though nothing needs those bytes to be buffered together.takeIntnow reads straight from the buffer when the bytes are all there. Otherwise a cold, out-of-line path copies them out withreadSliceAll, which works across refills.ReaderBufferTooSmallis now only returned for strings that have to be buffered whole, such as struct field names, and its doc comment says so.The test that expected
ReaderBufferTooSmallfor 1–7 byte buffers now expects those buffers to decode. It usesas_array, so field names don't get in the way. The test fails onmainand passes here. The test for a field name longer than the buffer still expects the error.Performance
This is not a performance change. I expected the fast path to save the guard's compare, but it doesn't. On canada (floats), decoding takes 3.74 M instructions per op here against 3.63 M on
main. Wall time on this i7-6700 swings between −12% and +22% depending on the binary, which is code layout, not this change. Twitter and small are within noise.The real per-value cost is elsewhere. The reader's
seek,endand buffer pointer live on the stack and are reloaded after every store into the output. Marking the readernoaliasdoesn't change that. Fixing it would need a decode path that keeps the cursor in a local variable.Tests pass on 0.16 and 0.17.