-
Notifications
You must be signed in to change notification settings - Fork 52
feat: Performance enhancements #1741
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
Conversation
# Conflicts: # src/test/java/dev/openfeature/sdk/benchmark/AllocationBenchmark.java
Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
# Conflicts: # src/main/java/dev/openfeature/sdk/ImmutableMetadata.java
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1741 +/- ##
============================================
+ Coverage 92.51% 93.66% +1.15%
- Complexity 593 601 +8
============================================
Files 53 55 +2
Lines 1403 1406 +3
Branches 150 154 +4
============================================
+ Hits 1298 1317 +19
+ Misses 64 50 -14
+ Partials 41 39 -2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
src/test/java/dev/openfeature/sdk/benchmark/AllocationBenchmark.java
Outdated
Show resolved
Hide resolved
src/test/java/dev/openfeature/sdk/benchmark/AllocationBenchmark.java
Outdated
Show resolved
Hide resolved
Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
|
/gemini review |
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.
Code Review
This pull request introduces several performance enhancements aimed at reducing memory allocations. The changes include using singleton EMPTY instances for various classes, replacing object builders with direct constructor calls, removing Optional usage in favor of direct null checks, and pre-sizing HashMaps. These are all excellent optimizations that contribute to the stated goal of reducing memory footprint. I've added a couple of suggestions to further refine the HashMap pre-sizing logic for even better performance. Overall, this is a great set of improvements.
| Map<String, Value> copy = new HashMap<>(); | ||
| Map<String, Value> copy; | ||
| if (in != null) { | ||
| var numMappings = in.size() + 1; |
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.
To make the HashMap pre-sizing more accurate, you can check if targetingKey is non-null here. This avoids overallocating when targetingKey is null, which is a good practice for performance-sensitive code.
| var numMappings = in.size() + 1; | |
| var numMappings = in.size() + (targetingKey != null ? 1 : 0); |
| copy.put(key, cloned); | ||
| } | ||
| } else { | ||
| copy = new HashMap<>(1); |
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.
| for (int j = 0; j < 2; j++) { | ||
| blackhole.consume(state.client.getBooleanValue(BOOLEAN_FLAG_KEY, false)); | ||
| blackhole.consume(state.client.getStringValue(STRING_FLAG_KEY, "default")); | ||
| blackhole.consume(state.client.getIntegerValue(INT_FLAG_KEY, 0, state.invocationContext)); | ||
| blackhole.consume(state.client.getDoubleValue(FLOAT_FLAG_KEY, 0.0)); | ||
| blackhole.consume(state.client.getObjectDetails( | ||
| OBJECT_FLAG_KEY, new Value(new ImmutableStructure()), state.invocationContext)); | ||
| } | ||
|
|
||
| OpenFeatureAPI.getInstance().setTransactionContext(new ImmutableContext(state.transactionAttr2)); | ||
|
|
||
| for (int j = 0; j < 2; j++) { | ||
| blackhole.consume(state.client.getBooleanValue(BOOLEAN_FLAG_KEY, false)); | ||
| blackhole.consume(state.client.getStringValue(STRING_FLAG_KEY, "default")); | ||
| blackhole.consume(state.client.getIntegerValue(INT_FLAG_KEY, 0, state.invocationContext)); | ||
| blackhole.consume(state.client.getDoubleValue(FLOAT_FLAG_KEY, 0.0)); | ||
| blackhole.consume(state.client.getObjectDetails( | ||
| OBJECT_FLAG_KEY, new Value(new ImmutableStructure()), state.invocationContext)); | ||
| } |
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.
There is significant code duplication in the context benchmark method, and also between context and main. To improve readability and maintainability, you could extract the repeated block of flag evaluation calls into a private helper method. For example:
private static void runEvals(Blackhole blackhole, AllocationBenchmarkState state, int iterations) {
for (int j = 0; j < iterations; j++) {
blackhole.consume(state.client.getBooleanValue(BOOLEAN_FLAG_KEY, false));
blackhole.consume(state.client.getStringValue(STRING_FLAG_KEY, "default"));
blackhole.consume(state.client.getIntegerValue(INT_FLAG_KEY, 0, state.invocationContext));
blackhole.consume(state.client.getDoubleValue(FLOAT_FLAG_KEY, 0.0));
blackhole.consume(state.client.getObjectDetails(
OBJECT_FLAG_KEY, new Value(new ImmutableStructure()), state.invocationContext));
}
}You can then call this helper from both context() and main().
|
I'll merge this one tomorrow @chrfwow . Up to you if you want to address the minor Gemini issues. |
Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
|



This Pr introduces some performance enhacements, that together yield the following results:
Baseline (
AllocationBenchmark.mainrun five times with the IntelliJ Profiler and averaged):runtime: 5329 ms
memory allocations: 16.47 GB
This PR:
runtime: 5404ms (no significant change, the deviation of runs is quite large)
memory allocations: 14.62 GB