Skip to content

perf: skip unmodifiableMap wrapper when hookHints is empty#1953

Open
tobias-ibounig-dt wants to merge 4 commits into
open-feature:mainfrom
tobias-ibounig-dt:perf/pr-2-hook-hints
Open

perf: skip unmodifiableMap wrapper when hookHints is empty#1953
tobias-ibounig-dt wants to merge 4 commits into
open-feature:mainfrom
tobias-ibounig-dt:perf/pr-2-hook-hints

Conversation

@tobias-ibounig-dt

Copy link
Copy Markdown
Contributor

This PR

  • Skips the Collections.unmodifiableMap() wrapper when hookHints is empty (the common case)

Related Issues

None

Notes

hookHints is resolved once per flag evaluation. Previously it was always wrapped in an unmodifiable view, even when empty. This PR avoids that allocation by returning Collections.emptyMap() directly when there are
no hints.

Allocation impact is negligible, but reduces on totalAllocatedInstances can be seen.

Metric main (baseline) PR 2 Delta
run:+totalAllocatedBytes 124,265,984 124,268,232 ~0 (noise)
run:+totalAllocatedInstances 2,723,316 2,691,291 −32,025 (−1.2%)

Follow-up Tasks

  • More PRs with memory improvements
  • Update benchmark.txt after all are applied

@tobias-ibounig-dt tobias-ibounig-dt requested review from a team as code owners June 5, 2026 08:27

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 optimizes the initialization of hookSupportData.hints in OpenFeatureClient.java by using Collections.emptyMap() when the hook hints are empty. A review comment points out that getHookHints() could return null, which would cause a NullPointerException when calling isEmpty(), and suggests adding a null check to handle this case safely.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +173 to +174
var hookHints = flagOptions.getHookHints();
hookSupportData.hints = hookHints.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(hookHints);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If flagOptions.getHookHints() returns null (which can happen if hookHints is explicitly set to null via the builder in FlagEvaluationOptions), calling hookHints.isEmpty() will throw a NullPointerException.

To ensure robust defensive programming, we should handle the null case gracefully by defaulting to Collections.emptyMap().

Suggested change
var hookHints = flagOptions.getHookHints();
hookSupportData.hints = hookHints.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(hookHints);
var hookHints = flagOptions.getHookHints();
hookSupportData.hints = hookHints == null || hookHints.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(hookHints);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is something that should be handled in the builder, but idk if we can modify this, since I assume it will be a lombok builder. Can we add a test to make sure we won't have a NPE?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ensured in builder that it can't be null

Signed-off-by: Tobias Ibounig <tobias.ibounig@dynatrace.com>
@toddbaert

Copy link
Copy Markdown
Member

Same codecov-action issue as #1955 (comment) - rebasing this PR onto main should fix it. cc @chrfwow

Signed-off-by: Tobias Ibounig <tobias.ibounig@dynatrace.com>
@tobias-ibounig-dt

Copy link
Copy Markdown
Contributor Author

Realized another thing in FlagEvaluationOptions. Builder Default is currently new HashMap<>();, would it make sense to change this to Collections.emptyMap()?
Didn't do it yet, as it could theoretically break someone doing something like getHookHints().put(...).
Any preference from your side?

@tobias-ibounig-dt tobias-ibounig-dt requested a review from chrfwow June 8, 2026 15:39
@codecov

codecov Bot commented Jun 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.28%. Comparing base (58091f3) to head (aad8866).
⚠️ Report is 10 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #1953      +/-   ##
============================================
+ Coverage     92.27%   93.28%   +1.01%     
- Complexity      653      658       +5     
============================================
  Files            59       59              
  Lines          1592     1594       +2     
  Branches        179      181       +2     
============================================
+ Hits           1469     1487      +18     
+ Misses           76       62      -14     
+ Partials         47       45       -2     
Flag Coverage Δ
unittests 93.28% <100.00%> (+1.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread src/test/java/dev/openfeature/sdk/HookSpecTest.java Outdated
Signed-off-by: Tobias Ibounig <tobias.ibounig@dynatrace.com>
@chrfwow

chrfwow commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

The current build issue can be fixed by running spotless:apply

Signed-off-by: Tobias Ibounig <tobias.ibounig@dynatrace.com>
@tobias-ibounig-dt

Copy link
Copy Markdown
Contributor Author

The current build issue can be fixed by running spotless:apply

Oh sorry, I thought I made sure to run it every time.

@sonarqubecloud

sonarqubecloud Bot commented Jun 9, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants