-
Notifications
You must be signed in to change notification settings - Fork 39
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
perf: add heap benchmark and reduce allocations #1156
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1156 +/- ##
============================================
- Coverage 93.71% 93.20% -0.52%
- Complexity 429 437 +8
============================================
Files 40 40
Lines 1019 1016 -3
Branches 72 84 +12
============================================
- Hits 955 947 -8
- Misses 40 42 +2
- Partials 24 27 +3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
@@ -0,0 +1,239 @@ | |||
[INFO] Scanning for projects... |
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.
I don't care if we commit this or not, but I think we should for records.
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
protected Map<String, Value> getAttributes() { | ||
if (attributes == null) { | ||
attributes = new HashMap<>(); | ||
} | ||
return attributes; | ||
} |
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.
perf: lazily initialize.
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.
Makes it non thread safe?
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.
Excellent point. I've reverted this because it's not a even a substantial savings. The bench result barely changes.
for (Hook hook : hooks) { | ||
if (hook.supportsFlagValueType(flagValueType)) { | ||
executeChecked(hook, hookCode, hookMethod); | ||
} | ||
} |
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.
perf: streams 😢
for (Hook hook : hooks) { | ||
if (hook.supportsFlagValueType(flagValueType)) { | ||
hookCode.accept(hook); | ||
} | ||
} |
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.
perf: streams 😢
List<Hook> reversedHooks = new ArrayList<>(hooks); | ||
Collections.reverse(reversedHooks); | ||
EvaluationContext context = hookCtx.getCtx(); | ||
for (Hook hook : reversedHooks) { | ||
if (hook.supportsFlagValueType(flagValueType)) { | ||
Optional<EvaluationContext> optional = Optional.ofNullable(hook.before(hookCtx, hints)) | ||
.orElse(Optional.empty()); | ||
if (optional.isPresent()) { | ||
context = context.merge(optional.get()); | ||
} | ||
} | ||
} | ||
return context; |
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.
perf: streams 😢
private static Map<String, Value> copyAttributes(Map<String, Value> in) { | ||
Map<String, Value> copy = new HashMap<>(); | ||
for (Entry<String, Value> entry : in.entrySet()) { | ||
copy.put(entry.getKey(), | ||
Optional.ofNullable(entry.getValue()).map((Value val) -> val.clone()).orElse(null)); | ||
} | ||
return copy; | ||
} |
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.
perf: common, non-stream method to copy.
if (overridingContext == null || overridingContext.isEmpty()) { | ||
return this; | ||
} | ||
if (this.isEmpty()) { | ||
return overridingContext; |
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.
perf: quit early with less HashMap
instantiations
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
|
||
AbstractStructure() { | ||
this.attributes = new HashMap<>(); | ||
// intentionally don't initialize the attributes - do this lazily |
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 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.
Reverted for: #1156 (comment)
protected Map<String, Value> getAttributes() { | ||
if (attributes == null) { | ||
attributes = new HashMap<>(); | ||
} | ||
return attributes; | ||
} |
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.
Makes it non thread safe?
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Quality Gate passedIssues Measures |
This PR reduces allocations of heap objects by ~70% for most use-cases. It does this by removing some usage of the streams API in some hotspots, and also being more efficient with
HashMaps
and context merging.Benchmark results before/after these changes:
The performance optimizations are not very cool or exciting; mostly try to avoid creating unnecessary
HashMaps
and don't use streams in hot paths (like context merging in hooks).