RFR: 8371656: HashMap.putAll() optimizations [v3]
Rémi Forax
forax at openjdk.org
Wed Feb 4 21:12:28 UTC 2026
On Thu, 4 Dec 2025 14:59:33 GMT, jengebr <duke at openjdk.org> wrote:
>> # 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...
>
> jengebr has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains five additional commits since the last revision:
>
> - Merge branch 'openjdk:master' into putMapEntriesOptimizations
> - Unit test revisions
> - Bug fix & unit test
> - fixing whitespace
> - Optimizing HashMap.putAll() and .<init> for HashMap and C$UM
src/java.base/share/classes/java/util/HashMap.java line 496:
> 494: }
> 495:
> 496: @SuppressWarnings({"unchecked"})
please remove
src/java.base/share/classes/java/util/HashMap.java line 516:
> 514: */
> 515: final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
> 516: if (m.getClass() == Collections.UnmodifiableMap.class) {
I would address that issue in a separate bug.
src/java.base/share/classes/java/util/HashMap.java line 538:
> 536:
> 537: if (m.getClass() == HashMap.class) {
> 538: @SuppressWarnings("unchecked")
remove the @SupressWarning and add the ? extends to the cast below, this is a safe cast
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/28243#discussion_r2765980529
PR Review Comment: https://git.openjdk.org/jdk/pull/28243#discussion_r2765983153
PR Review Comment: https://git.openjdk.org/jdk/pull/28243#discussion_r2765987296
More information about the core-libs-dev
mailing list