-
Notifications
You must be signed in to change notification settings - Fork 1k
Add TagReplacingFilter #6183
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
base: main
Are you sure you want to change the base?
Add TagReplacingFilter #6183
Conversation
16cea7d
to
6eb2663
Compare
while (iterator.hasNext()) { | ||
Tag tag = iterator.next(); | ||
String key = tag.getKey(); | ||
String value = tag.getValue(); |
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 bit of hacky move that can be hindering performance instead of helping it. The idea is simple - since predicate and replacing function aren't really interested in the tag itself, only in the key and value, let's extract them once, store in registers, and prevent double memory access. This sounds good, but in reality it might end up with two additional stack writes (which are relatively cheap and wouldn't make that much difference): if for any reason compiler can't fully inline the predicate and function, it will have to store the registers on the stack, and instead of one tag reference it will be forced to store one tag and two string references. However, this still saves us one indirection.
TBH this is solved simply by running a pair of benchmarks, but i'm all out of energy, and there are a couple more PRs coming
fccafc5
to
4de70ed
Compare
Signed-off-by: etki <[email protected]>
Signed-off-by: etki <[email protected]>
4de70ed
to
8364f76
Compare
|
||
return id.replaceTags(tags); | ||
} | ||
}; |
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.
What were the problems / what was solved:
- Stream was quite allocateful for a handful of elements. We're usually OK for that in writing our applications, but for critical paths we'd like to avoid that
- for (String exception : exceptions) was adding O(n²) complexity
- toList() creates a new zero-sized list. This results in (usually) a number of unnecessary resizes.
- Finally, we'd like to abstain from recreating meter if there were no actual replacements. This doesn't do really much, but just a pleasant addition + even if we've allocated a new list, there is no record in GC card table pointing at it.
Hey. This is a PR aimed at performance. Currently, MeterFilter.replaceTagValues uses an anonymous class with several drawbacks:
PR addresses these issues and wins some performance. As with another PR, implementing suggestions in #6113 may easily boost wins by a magnitude. Benchmarks from #6174, OpenJDK 21.0.2 and Intel N100 fixed at 2GHz were used to evaluate the impact. The benchmark was fed with identifiers having 0-64 tags, 90% of time having exactly
mode
tags, and any other number with even probability otherwise. Please be aware that these results include some of the updates to Tags from a forthcoming PR; i might be able to re-run the benchmarks without Tags updates, but i'm not sure i'll have the time.233.983 ± 0.485
85.120 ± 5.041
285.697 ± 0.620
125.450 ± 0.754
353.423 ± 1.433
145.541 ± 5.641
411.847 ± 0.868
177.064 ± 1.155
570.672 ± 1.713
244.465 ± 1.372
916.877 ± 0.992
417.049 ± 2.131
1587.275 ± 1.791
869.795 ± 15.653
2208.968 ± 12.309
1640.243 ± 33.729
Please note that of course for 0 tags it would take less than 10ns, and other lower amounts would also have lower processing time - it's the fact that 10% of identifiers in the sample set possess 0-64 tags and drag the time higher by that.