RFR: 8371656: HashMap.putAll() optimizations [v4]
jengebr
duke at openjdk.org
Wed Feb 11 15:28:56 UTC 2026
> # HashMap.putAll() optimizations: Eliminating Megamorphic Call Site Bottlenecks
>
> ## Summary
>
> This PR addresses performance bottlenecks in `HashMap.putMapEntries()` by implementing direct optimizations for specific input types: `j.u.HashMap` and `j.u.Collections$UnmodifiableMap`. The optimizations target `HashMap(Map)` constructor and `putAll()` operations based on the real-world megamorphic behavior identified in [JDK-8368292](https://bugs.openjdk.org/browse/JDK-8368292), delivering significant performance improvements when multiple `Map` subtypes are used.
>
> ## Problem Context
>
> ### Megamorphic Call Site Overhead in Map Iteration
> `HashMap.putMapEntries()` currently uses a generic approach that suffers from megamorphic call site overhead when applications perform bulk creation or population of HashMaps from various source map types:
>
> 1. `m.entrySet()` becomes megamorphic across different map implementations
> 2. `entrySet().iterator()` creates different iterator types
> 3. `entry.getKey()` and `entry.getValue()` calls vary by map type
> 4. Individual `putVal()` calls for each entry
>
> When the source is `Collections$UnmodifiableMap`, the problem is compounded by megamorphic wrappers around the already-megamorphic iteration methods. In cases where the unwrapped map is also a HashMap, both the wrapper overhead and the iteration overhead can be eliminated with a single optimization.
>
> ## Optimized Methods
>
> ### HashMap
> - **`putMapEntries(Map<? extends K, ? extends V> m, boolean evict)`**: Added fast paths for UnmodifiableMap unwrapping and HashMap-to-HashMap copying
> - **`putMapEntries(HashMap<? extends K, ? extends V> src, boolean evict)`**: copies HashMap-to-HashMap via direct Node processing. Avoids polymorphic issues and eliminates redundant calls to HashMap.hash().
>
> ## Implementation Details
>
> ### HashMap-to-HashMap Fast Path
> Eliminates megamorphic iteration by targeting internal Node structure - and also reuses the pre-calculated hash code, thus avoiding megamorphic calls to Object.hashCode() and the sometimes-expensive recalculation (depending on key type). This also eliminates direct reads from the key, thus reducing the set of objects accessed.
>
> ### UnmodifiableMap Unwrapping
> Detects UnmodifiableMap instances and accesses the underlying map directly via the `m` field, eliminating wrapper-induced megamorphic call sites. UnmodifiableMap visibility changed from `private` to package-private to enable this direct access.
>
> ## Performance Impact
>
> | Source Type | Size |...
jengebr has updated the pull request incrementally with one additional commit since the last revision:
Addressing CR feedback (formatting + safe casts)
-------------
Changes:
- all: https://git.openjdk.org/jdk/pull/28243/files
- new: https://git.openjdk.org/jdk/pull/28243/files/1b09326c..bae73f88
Webrevs:
- full: https://webrevs.openjdk.org/?repo=jdk&pr=28243&range=03
- incr: https://webrevs.openjdk.org/?repo=jdk&pr=28243&range=02-03
Stats: 9 lines in 1 file changed: 0 ins; 2 del; 7 mod
Patch: https://git.openjdk.org/jdk/pull/28243.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/28243/head:pull/28243
PR: https://git.openjdk.org/jdk/pull/28243
More information about the core-libs-dev
mailing list