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
op-batcher: Embed Zlib Compressor into Span Channel Out ; Compression Avoidance Strategy #10002
Conversation
cb3df28
to
58dfa9d
Compare
WalkthroughWalkthroughThe recent updates focus on enhancing channel and compressor functionalities in a batch processing system. Changes include implementing a factory pattern for dynamic channel creation based on batch types, removing the Changes
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configration File (
|
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 wondering if an additional unit test of the SpanChannelOut
would be good that covers both cases:
- adding block n-1 exits early in the threshold check, so no compression, then adding block n makes it full
- adding block n-1 doesn't exits early in the threshold check, so compression does happen, which then stays under the threshold, then adding block n makes it full
not sure which case is currently covered.
39b7702
to
824510e
Compare
824510e
to
b251dec
Compare
b251dec
to
fc1e4ce
Compare
fc1e4ce
to
a513927
Compare
a513927
to
852a342
Compare
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.
Awesome work, thanks ✨🔴
a24dfe1
to
3fdc30a
Compare
What
Moves compressor handling directly to the Span Channel Out, and implements a compression avoidance strategy.
Why
Because Span Batches are not streaming structures, there is not much value in using the existing Compressor Interfaces for Span Channel Out. And actually, handling this difference in behavior costs us complexity and performance.
By moving Compression directly to the Span Channel Out, we achieve fewer buffer writes, more careful control of the compression buffer, and also achieve a simple optimization to avoid compression in the majority of cases
How
Embedded Compression
zlib.Writer
directly into the Span Channel Out and rewrote theAppendSingularBatch
functionNewSingularChannelOut
vsNewSpanChannelOut
. When building span channels, theTargetOutput
that would normally build a compressor is instead passed directly to the Channel OutCompression Avoidance
The size of the RLP structure is taken into account before compressing. Now, if the RLP size is smaller than the compression target (aka, the uncompressed data is already small enough), no compression is done. And whenever compression is done, the uncompressed RLP size is recorded. The logic is as follows:
This causes the compression to only happen at required times. The first time the uncompressed data surpasses the target, it becomes compressed, and the threshold is no longer exceeded. It then won't compress again until the uncompressed data takes up all the remaining space.
In production with a compression ratio of ~40%, we achieve a ~log(n) number of total compressions for a span batch during its construction.
Testing
Performance Testing
Our random blocks do not see a great compression ratio. I confirmed this on commits prior to the changes here in this PR. This means that once the compression threshold is met the first time, it is already nearly full and will compress on most subsequent
AppendSingularBatch
calls.However, even with the lower quality compression, the benefits of compression avoidance is still visible. I wrote a benchmark which incrementally adds to a Batch. It's a bit of a hack on the Go Benchmark Sub-Benchmark system, but it will take an empty Batch/SpanBatch and will create a new benchmark test case for every batch of X (default 100) batches. The time it takes to add those 100 batches is considered the test time, and then the next test case is the next 100 batches.
New test cases are added until the channel is full. I used a Compressor with a "Real" configuration in order to test real compression limits.
Old Performance:
New Performance:
Reading these results
Notably, adding the first 100 batches is now 40x faster. And adding the 500-600th batches is 90x faster.
Once compression is required, the speed is still ~5x faster, which is likely due to there being fewer layers of buffers to manage in the new Span Channel Out.
We can also turn the batch-count down on the test to see the behavior in a more granular way:
The last 25 batches added
develop
The last 25 batches added
this code
You can see that the new compression avoidance keeps runtime low even near the end of the execution, where the old code was consistently doing all the work of compression.