[Endpoints BDD 4/5] Avoid eager map allocation when building an Endpoint - #7317
Merged
alextwoods merged 1 commit intoAug 27, 2026
Merged
Conversation
alextwoods
force-pushed
the
alexwoo/endpoints-bdd-pr4
branch
from
August 26, 2026 03:44
4a76bcc to
13c4e1d
Compare
alextwoods
force-pushed
the
alexwoo/endpoints-bdd-pr4
branch
from
August 26, 2026 21:16
13c4e1d to
8f6d3cf
Compare
alextwoods
marked this pull request as ready for review
August 26, 2026 21:26
Base automatically changed from
alexwoo/endpoints-bdd-pr3
to
feature/master/endpoints-bdd
August 26, 2026 21:49
Endpoint's builder eagerly allocated two HashMaps (headers and attributes) for every endpoint, and handed them to the built Endpoint. Both escape into the result, so they cannot be optimized away by the JIT, and most endpoints need neither: headers are almost always absent and attributes are almost always a single AUTH_SCHEMES entry. Stage instead of allocate: - The header map is allocated only once a header is actually added. - The first attribute is held in two fields on the builder; a map is allocated only if a second distinct key arrives. - build() collapses whatever was staged into the smallest immutable map that fits: emptyMap, singletonMap, or an unmodifiable view. - Both maps are created with capacity 4 rather than the default 16, whose backing table was the largest single allocation on the path. No API change. The builder itself does not escape resolveEndpoint, so escape analysis already eliminates it; this removes the allocations that actually survive. Measured with JMH (allocation profiler, 2 forks, JDK 21, M-series), against an Endpoint-shaped holder built only from emptyMap/singletonMap as the theoretical floor: shape before after floor no attributes 120 B/op 24 B/op 24 B/op one attribute 232 B/op 64 B/op 64 B/op two attributes 264 B/op 232 B/op one attr + header 424 B/op 288 B/op The two shapes that dominate real endpoint rules now allocate exactly what a hand-written factory would. Time per construction drops 67% and 71% for those two shapes. Two-attribute construction costs ~3ns more because it stages an attribute and then promotes anyway; that path is S3 Express only and 3ns against a ~50us endpoint resolution. Behavior notes: - headers() and the attribute map are now unmodifiable. Mutating a map returned from a getter was never supported, and SdkHttpRequest already behaves this way. - Mutating a builder after build() no longer leaks into the Endpoint that was already built, for the no-attribute, single-attribute and header cases. Previously it leaked in every case. The two-or-more attribute case still shares state, unchanged from before.
alextwoods
force-pushed
the
alexwoo/endpoints-bdd-pr4
branch
from
August 26, 2026 21:49
8f6d3cf to
17934a6
Compare
davidh44
approved these changes
Aug 26, 2026
alextwoods
merged commit Aug 27, 2026
91541fd
into
feature/master/endpoints-bdd
4 of 5 checks passed
|
This pull request has been closed and the conversation has been locked. Comments on closed PRs are hard for our team to see. If you need more assistance, please open a new issue that references this one. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[Endpoints BDD 4/5] Avoid eager map allocation when building an Endpoint
This PR is 4/5 for the Endpoints BDD:
Note: This PR merges to the feature/master/endpoints-bdd feature branch and NOT to master.
Motivation
Endpoint's builder eagerly allocated twoHashMaps for headers and attributes for every endpoint, and passed them to the builtEndpoint. Both escape into the result, so the JIT cannot remove them. Most endpoints need neither: headers are almost always absent, and attributes are almost always empty or a singleAUTH_SCHEMESentry.The builder itself does not escape
resolveEndpoint, so escape analysis already eliminates it. This PR removes the allocations that actually survive.No API change — no new methods, no signature changes.
Modifications
build()collapses whatever was staged into the smallest immutable map that fits:emptyMap,singletonMap, or an unmodifiable view.Benchmarks
JMH, allocation profiler, 2 forks, JDK 21, M-series. "Floor" is an
Endpoint-shaped holder built only fromemptyMap/singletonMap— what a hand-written static factory would allocate.Testing
toBuilder()round-trips across all arities, andheaders()immutability for both empty and populated maps.