Repository navigation
Conversation
|
/gemini review |
There was a problem hiding this comment.
📋 Review Summary
This PR introduces targeted Cython and Python fast-path optimizations for AbstractComponentCoderImpl, TupleCoderImpl, and SequenceCoderImpl, along with fixing AbstractComponentCoderImpl.estimate_size to forward the nested parameter. The changes are clean, preserve coder semantics, and are well-supported by microbenchmark and end-to-end Dataflow benchmark results.
🔍 General Feedback
- The fast paths for
tuple/listchecks and theif child_observables:guard inAbstractComponentCoderImpl.get_estimated_size_and_observablestranslate directly into fast C-level checks in Cython without unnecessary allocations or attribute lookups. - One minor accidental change in
coder_impl.pxdonWindowedValueCoderImpl.get_estimated_size_and_observablesis noted inline.
💡 Tip: Comment /gemini review on this pull request to trigger a new Gemini code review.
| cdef libc.stdint.int64_t _from_normal_time(self, libc.stdint.uint64_t value) | ||
|
|
||
| @cython.locals(c=CoderImpl) | ||
| @cython.locals(c=CoderImpl, i=int, last=int, num_coders=int) |
There was a problem hiding this comment.
🟢 Low: WindowedValueCoderImpl.get_estimated_size_and_observables does not use i, last, or num_coders. It looks like this @cython.locals decorator was unintentionally updated alongside AbstractComponentCoderImpl.get_estimated_size_and_observables.
| @cython.locals(c=CoderImpl, i=int, last=int, num_coders=int) | |
| @cython.locals(c=CoderImpl) |
There was a problem hiding this comment.
Fixed in 91f182a: reverted @cython.locals on WindowedValueCoderImpl.get_estimated_size_and_observables back to @cython.locals(c=CoderImpl).
|
/gemini review |
There was a problem hiding this comment.
📋 Review Summary
This PR introduces targeted Cython and hot-path optimizations to AbstractComponentCoderImpl, TupleCoderImpl, and SequenceCoderImpl in coder_impl.py and coder_impl.pxd. The changes are clean, preserve existing semantics (while fixing nested forwarding in AbstractComponentCoderImpl.estimate_size), and address the previous review feedback.
🔍 General Feedback
- Typing the loop variables (
i,last,num_coders) inAbstractComponentCoderImpl.get_estimated_size_and_observablesand guardingobservables += child_observablescleanly avoids unnecessary Cython object overhead and empty list extensions. - Fast-pathing
tupleandlistchecks inTupleCoderImplandSequenceCoderImpl.encode_to_streamavoids redundant allocations and attribute lookups in tight encoding/estimation loops. - Forwarding
nested=nestedinAbstractComponentCoderImpl.estimate_sizeensures accurate size estimation for nested variable-length last components.
💡 Tip: Comment /gemini review on this pull request to trigger a new Gemini code review.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #41217 +/- ##
============================================
+ Coverage 57.48% 57.63% +0.15%
Complexity 2492 2492
============================================
Files 1204 1198 -6
Lines 171265 171203 -62
Branches 2103 2103
============================================
+ Hits 98456 98680 +224
+ Misses 70157 69871 -286
Partials 2652 2652
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Description
Optimizes
AbstractComponentCoderImpl.estimate_size,TupleCoderImpl, andSequenceCoderImplinsdks/python/apache_beam/coders/coder_impl.pyandsdks/python/apache_beam/coders/coder_impl.pxd:AbstractComponentCoderImpl.get_estimated_size_and_observables: Types loop variables (i=int, last=int, num_coders=int) incoder_impl.pxd, guardsif child_observables: observables += child_observablesto avoid extending an empty list on every component, and forwardsnested=nestedfromestimate_size.TupleCoderImpl._extract_componentsand_construct_from_components: Avoids copyingtuple(value)/tuple(components)when the input is already atuple(orlistfor extraction).SequenceCoderImpl.encode_to_stream: Short-circuitstype(value) is tuple or type(value) is listbefore callinghasattr(value, "__len__").Benchmarks & Performance Impact
upstream/mastervsupstream/master+ this PR alone):bench_18_tuple_and_sequence_coder_impl(c2feb961eef) (on branchperf/py-benchmarks-suite) — 300,000SequenceCoderImpl.encodeandTupleCoderImpl.estimate_sizecalls improved from209.90 ms->148.70 ms(1.41xfaster,-29.2%,-61.20 ms) in compiled Cython.79.4%of savings,-41.63 ms): OptimizingAbstractComponentCoderImpl.get_estimated_size_and_observables(if child_observables:guard, typed loop locals, andTupleCoderImpl._extract_componentstuple pass-through) —126.00 ms->84.37 ms(1.49xfaster,-33.0%).20.6%of savings,-10.81 ms): Short-circuitingtype(value) is tuple or type(value) is listbeforehasattr(value, "__len__")inSequenceCoderImpl.encode_to_stream—63.62 ms->52.81 ms(1.20xfaster,-17.0%).core_window_row_combine): Included inrun_core_window_row_combine_pipeline(c2feb961eef) (3,000,000 generated events -> 9,000,000 sliding-windowed elements on a singlen2-standard-4worker), which improved end-to-end worker stage execution time by 1.80x (-44.5%,599.6s->332.9s) and reduced total billable Dataflow vCPU/Memory/PD usage by-26.1%(1,134->838vCPU-s).Testing
pytest sdks/python/apache_beam/coders/coders_test.py sdks/python/apache_beam/coders/fast_coders_test.py.