Uh oh!
There was an error while loading. Please reload this page.
[BEAM-14166] Performance improvements for RowWithGetter - #17172
Conversation
mosche
commented
Mar 24, 2022
R: @TheNeuralBit |
81faf59 to
9ddc834Comparereuvenlax
commented
Mar 24, 2022
By default, getValue results in generated bytecode to fetch the value. Is this cache really more efficient than the generated bytecode? |
TheNeuralBit
commented
Mar 24, 2022
Maybe some microbenchmarks could help here |
@reuvenlax certainly a valid question and I'm happy to discuss what's worth caching. Though, the key point here is, that there's already a cache in place for array, iterable and map types. Processing for these is currently not ideal. For instance, looking at an array field the following steps happen on
The problem is really on the 2nd access. Step 1) is repeated, but step 2) uses the cache discarding all the work of step 1). This PR mostly addresses some of the inconsistencies using the existing cache and reduces the overhead of the cache by choosing better fitted data structures to store cached values. |
mosche
commented
Mar 24, 2022
Considering that elements of For And if a cache is used, then any composite |
mosche
commented
Mar 25, 2022
I started doing some jmh benchmarks for |
reuvenlax
commented
Mar 28, 2022
Benchmarks of this code are tricky to do, since the cost of codegen tends to dominate microbenchmarks. |
mosche
commented
Mar 29, 2022
I've pushed my benchmark code for reference, let me know if you have any suggestions. To prevent the issue you've mentioned @reuvenlax, I'm setting up a relatively large number of rows as JMH state before the actual benchmark invocation. To establish a baseline, I'm looking at
These numbers are certainly not very much in favour of the status quo. |
mosche
commented
Apr 1, 2022
I've drilled down into this a bit and I think I've got some interesting finding's to share @reuvenlax & @TheNeuralBit. Investigating a few approaches, I would to suggest to push field type based logic in I also looked a bit into costs of caching, the picture isn't as clear there. The costs of initializing any data structure facilitating a cache is certainly high compared to the costs of calling getters. One finding though was that On the other hand, I'm not sure what the original motivation for adding a field value cache in Some visualizations for a few selected runs: |
9ddc834 to
c06f88bComparemosche
commented
Apr 11, 2022
Run Java PreCommit |
…reeMap to reduce memory footprint of field value cache.
c06f88b to
f57b9f2Comparemosche
commented
Apr 12, 2022
Run Java PreCommit |
1 similar comment
mosche
commented
Apr 12, 2022
Run Java PreCommit |
mosche
commented
Apr 12, 2022
@TheNeuralBit@reuvenlax Please let me know how / if you wanna proceed here, so I can wrap up my initial PR #16947 accordingly. In any case, it was a very interesting dive into Beam Schemas. Thanks for all the pointers. |
mosche
commented
Apr 19, 2022
aromanenko-dev
commented
Apr 27, 2022
@TheNeuralBit@reuvenlax |
TheNeuralBit
commented
May 11, 2022
Run SQL PostCommit |
TheNeuralBit
commented
May 11, 2022
Run Java PreCommit |
TheNeuralBit
left a comment
There was a problem hiding this comment.
Thanks @mosche for the extensive benchmarking, and apologies for the atrocious review latency!
I'm ok with this if it passes current tests, given the extensive benchmarking. A couple of things:
- I'd still like to get some final feedback on the approach from @reuvenlax, but I acn go ahead and merge next Monday if that doesn't happen this week.
- It could be interesting to run your benchmarks continuously to 1) monitor for regressions, and 2) give us a convenient way to test other potential improvements. Maybe file a jira for that if you don't have time now?
| @Nullable | ||
| ValueT get(ObjectT object); | ||
| default @Nullable Object getRaw(ObjectT object) { |
There was a problem hiding this comment.
nit: maybe getUntyped is a more appropriate name here?
Also could you clarify why we need this?
There was a problem hiding this comment.
Thanks so much for having a look @TheNeuralBit 🙏
getRaw() was based on a conversation with @reuvenlax.
getValues() is maybe poorly named - might be better called getRawValues. What you're looking for is probably the getBaseValues() method.
getValues is mostly used in code that knows exactly what it's doing for optimization purposes. It goes along with the attachValues method, which is similarly tricky to use. It's there to enable 0-copy code, but not necessarily intended for general consumption.
RowWithGetters.getValues() returns the "raw" unmodified result of the getters:
publicList<Object> getValues() {
returngetters.stream().map(g -> g.get(getterTarget)).collect(Collectors.toList());
}As I am pushing down the transformation of the getter result into the getter itself, I needed a way to bypass that in order to maintain the current semantics of getValues(). Let me know if the name makes sense given that context.
There was a problem hiding this comment.
Yeah that makes sense, thanks. Could you add some of this context in a comment there?
There was a problem hiding this comment.
@TheNeuralBit I've opened a new PR to add the missing comment, sorry for the delay.
#21982
reuvenlax
commented
May 11, 2022
via email
Let me take another look. IIRC I had some concerns, but it's possible that
the extensive benchmarking addressed those. …On Wed, May 11, 2022 at 2:58 PM Brian Hulette ***@***.***> wrote:
***@***.**** approved this pull request.
Thanks @mosche <https://github.com/mosche> for the extensive
benchmarking, and apologies for the atrocious review latency!
I'm ok with this if it passes current tests, given the extensive
benchmarking. A couple of things:
- I'd still like to get some final feedback on the approach from
@reuvenlax <https://github.com/reuvenlax>, but I acn go ahead and
merge next Monday if that doesn't happen this week.
- It could be interesting to run your benchmarks continuously to 1)
monitor for regressions, and 2) give us a convenient way to test other
potential improvements. Maybe file a jira for that if you don't have time
now?
------------------------------
In
sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/FieldValueGetter.java
<#17172 (comment)>:
> @@ -33,5 +33,9 @@
@nullable
ValueT get(ObjectT object);
+ default @nullable Object getRaw(ObjectT object) {
nit: maybe getUntyped is a more appropriate name here?
Also could you clarify why we need this?
—
Reply to this email directly, view it on GitHub
<#17172 (review)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AFAYJVOBUJMEVNFJNON7Y7DVJQUOVANCNFSM5RRHFBKQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
mosche
commented
May 17, 2022
@reuvenlax Kind ping, did you already get the chance to have another look at this? Just to make it clear, this is not about caching ... that was just a minor almost irrelevant part of this |
aaltay
commented
May 27, 2022
@reuvenlax - Would you be able to take another look? |
TheNeuralBit
commented
May 28, 2022
I think this is fine to go ahead and merge. From what I can tell Reuven's original concern was that this would start caching more types than were already being cached in |
aromanenko-dev
commented
May 30, 2022
@TheNeuralBit Thanks for moving forward and finally merge it! |
mosche
commented
May 30, 2022
@TheNeuralBit Thanks a lot 🙏 I still owe you the comment on |
mosche
commented
Jun 7, 2022
Resolves #21634 |
reuvenlax
commented
Oct 11, 2022
via email
Will look at it today or tomorrow - currently on a flight. …On Tue, May 17, 2022 at 3:52 AM Moritz Mack ***@***.***> wrote:
@reuvenlax <https://github.com/reuvenlax> Kind ping, did you already get
the chance to have another look at this? Just to make it clear, this is not
about caching ... that was just a minor almost irrelevant part of this
—
Reply to this email directly, view it on GitHub
<#17172 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AFAYJVOUKSLU2SLR3QEQZ3TVKNF5LANCNFSM5RRHFBKQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|

Push field type based logic in
RowWithGettersdown intoFieldValueGetters to remove any branching and allow for better inlining and switch to TreeMap for caching to minimize memory footprint. See benchmark results below.To not modify the behavior of
getValues(), related calls are delegated to the original getter as is.Thank you for your contribution! Follow this checklist to help us incorporate your contribution quickly and easily:
R: @username).[BEAM-XXX] Fixes bug in ApproximateQuantiles, where you replaceBEAM-XXXwith the appropriate JIRA issue, if applicable. This will automatically link the pull request to the issue.CHANGES.mdwith noteworthy changes.See the Contributor Guide for more tips on how to make review process smoother.
To check the build health, please visit https://github.com/apache/beam/blob/master/.test-infra/BUILD_STATUS.md
GitHub Actions Tests Status (on master branch)
See CI.md for more information about GitHub Actions CI.