perf: buffer accumulation in _write_query_params() reduces f.write() calls (~100ns improvement, 1.1-1.3x speedup) - #790
Conversation
bc1545f to
9b21d5b
Compare
|
Just spitting this here: Honest answer: on its own, ~100ns per call is tiny. But context matters:
|
f2be2a8 to
ac64459
Compare
ac64459 to
1e1e709
Compare
1e1e709 to
9a41e1f
Compare
|
Warning Review limit reachedNext included review available in 21 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: QUIET Plan: Advanced Run ID: 📒 Files selected for processing (3)
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 |
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Optimizes query-parameter serialization in protocol messages by buffering encoded parameter bytes and writing them in a single f.write(), reducing per-parameter write calls in hot paths.
Changes:
- Buffer-accumulate query parameter bytes in
_QueryMessage._write_query_params()and write once. - Remove redundant
ExecuteMessage._write_query_params()pass-through override. - Add unit tests validating serialization parity and add a local benchmarking script.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| cassandra/protocol.py | Implements buffered parameter encoding and removes redundant override to reduce overhead in execute/query paths. |
| tests/unit/test_protocol.py | Adds unit tests to validate the new buffered encoding matches prior write_value() behavior. |
| benchmarks/bench_execute_write_params.py | Adds a standalone benchmark script to compare encoding variants and measure performance. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
9a41e1f to
bba81b6
Compare
Replace the per-parameter write_value(f, param) loop in _QueryMessage._write_query_params() with a buffer accumulation approach: list.append + b"".join + f.write(), flushed in bounded 64KB chunks to avoid an unbounded transient allocation for large parameter sets (e.g. large vectors), addressing a peak-memory concern raised in review. This reduces the number of f.write() calls for typical param counts, which is significant for vector workloads with large parameters. Also removes the redundant ExecuteMessage._write_query_params() pass-through override to avoid extra MRO lookup per call. Includes 14 unit tests covering normal, NULL, UNSET, empty, large vector, and mixed parameter scenarios for both ExecuteMessage and QueryMessage. Test assertions tightened to check exact serialized bytes instead of substring containment. Includes a benchmark script (benchmarks/bench_execute_write_params.py), fixed for the current encode_message() signature and re-run to reflect actual measured numbers on this machine. Signed-off-by: Yaniv Michael Kaul <yaniv.kaul@scylladb.com>
bba81b6 to
c6460a3
Compare
Summary
Replace per-parameter
write_value(f, param)loops with buffer accumulation (list.append+b"".join+ singlef.write()), reducingf.write()calls from(2*N + 1)to 1 for N query parameters in the execute/query path. Accumulation is flushed in bounded 64KB chunks to avoid an unbounded transient allocation for very large parameter sets (e.g. large vectors), addressing a peak-memory concern raised in review.What changed
cassandra/protocol.py_QueryMessage._write_query_params()-- Buffer accumulation for the parameter loop, flushed viaf.write()once the accumulated size reaches_WRITE_QUERY_PARAMS_FLUSH_THRESHOLD(64KB) to bound peak memory.ExecuteMessage._write_query_params()-- Removed unnecessarysuper()pass-through override (now inherited directly from_QueryMessage).tests/unit/test_protocol.pyAdded 14 new test methods in
WriteQueryParamsBufferAccumulationTest, asserting exact serialized bytes (assertEqual/endswith) rather than substring containment.Benchmark
Re-measured on this machine with the included
benchmarks/bench_execute_write_params.py(min()oftimeit.repeat(repeat=5, number=500_000)). No compiled Cython.sowas available in this environment, so these are pure-Python numbers -- not directly comparable to the previous table, which assumed a Cython build.module (py)is the actual shipped_write_query_params()method call (includes real method-dispatch overhead);buf_accumis the standalone reference function used only for isolating the accumulation logic itself.The accumulation logic itself (
buf_accum) is consistently faster than the baseline loop. The actual method call (module (py)) is roughly flat-to-slightly-slower than baseline for small param counts on this pure-Python build, and about even for 10 params; the previously reported >1x speedups for the real method call were measured against a Cython-compiled build and are not reproducible here. As before, the clearer payoff is for largerNand inBatchMessage.send_body()(PR #791).Tests
tests/unit/test_protocol.pypasses in full (39 passed) in this environment