-
Notifications
You must be signed in to change notification settings - Fork 499
Optimize BufferedSubStream.ReadByte #912
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
| public override void Flush() { } | ||
|
|
||
| public override long Length => BytesLeftToRead; | ||
| public override long Length => BytesLeftToRead + _cacheLength - _cacheOffset; |
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.
It seems weird that Length in a stream refers only to the remaining portion, but since that's the way it already worked I assume it's for a reason.
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.
maybe that's not the contract but I "meant" to do it 😬
|
|
||
| private void RefillCache() | ||
| { | ||
| var count = (int)Math.Min(BytesLeftToRead, _cache.Length); |
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.
This is a new bit of logic here; the old code would always request _cache.Length bytes when refilling. It probably wasn't hurting anything but I figure it's better to request only what we need.
adamhathcock
left a comment
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.
Smells good, thanks!
| public override void Flush() { } | ||
|
|
||
| public override long Length => BytesLeftToRead; | ||
| public override long Length => BytesLeftToRead + _cacheLength - _cacheOffset; |
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.
maybe that's not the contract but I "meant" to do it 😬
In
BufferedSubStream, by changing whatBytesLeftToReadand_cacheLengthtrack, we can simplify the work to be done when reading a byte.BytesLeftToReadnow tracks the amount of completely unread/uncached data, and_cacheLengthtracks the total cache length including the consumed portion. Then we only need to update the cache offset when reading a byte. It also moves the logic to refresh the cache into its own method. Interestingly, only about half of the performance increase comes from simplifying the variable usage. The other half comes from moving out the cache refresh logic, presumably because it makes theReadBytemethod small enough for callers to inline.Core i7-6700k (1.7% reduction):
Apple M3 (2.8% reduction):
Time to extract a 14MB 7z. The benchmarks are with .NET 8.0 but it also helped slightly with .NET Framework 4.8 (~1.1% reduction).
I wish I could keep going with these optimization PRs but I think I'm out of ideas after this one 😄.