On Thu, 4 Dec 2025 14:59:33 GMT, jengebr <[email protected]> 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 >> Directly iterates over `src.table` to eliminate entrySet() allocation and >> polymorphic iterator calls, using the internal Node structure for maximum >> efficiency. >> >> ### 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 | Poisoned | Baseline | Optimized | Improvement | >> |-------------|------|----------|----------|-----... > > 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
@stuart-marks would you mind reviewing this one? It's conceptually similar to the ArrayList modifications, but applied to different classes and most details differ. I incorporated lessons about MOAT so that part should be cleaner. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28243#issuecomment-3633197823
