On Mon, 3 Nov 2025 20:45:44 GMT, jengebr <[email protected]> wrote:

> # JVM Collections Optimizations: Eliminating toArray() Performance Bottlenecks
> 
> ## Summary
> 
> This PR addresses performance bottlenecks in ArrayList.addAll() and 
> Collections.SingletonSet.toArray() methods by implementing direct 
> optimizations that bypass inefficient intermediate allocations and abstract 
> implementations. The optimizations target high-frequency operations 
> identified through profiling analysis, delivering 37% performance 
> improvements for ArrayList operations and 17-43% performance improvements for 
> SingletonSet operations under real-world conditions where multiple collection 
> types are used.
> 
> ## Problem Context
> 
> ### ArrayList.addAll() Inefficiency
> ArrayList.addAll() currently calls `c.toArray()` on the source collection to 
> avoid iterator-based copying, but this creates unnecessary intermediate array 
> allocation when the source is also an ArrayList. The method performs:
> 
> 1. Call `c.toArray()` - creates intermediate array
> 2. Call `System.arraycopy()` to copy from intermediate array to destination
> 3. Discard intermediate array
> 
> When both source and destination are ArrayList instances, this can be 
> optimized to direct array copying.
> 
> ### Collections.SingletonSet toArray() Missing Implementation
> Collections.SingletonSet inherits the default `AbstractCollection.toArray()` 
> implementation, which:
> 
> 1. Creates an Object[] of the expected size
> 2. Iterates through the collection (1 element)
> 3. Ensures "expected" size is the actual size
> 4. Returns the array
> 
> For a single-element collection, this overhead is disproportionate to the 
> actual work needed. Additionally, this implementation is vulnerable to call 
> site poisoning, showing 74-118% performance degradation under megamorphic 
> conditions.
> 
> ## Optimized Methods
> 
> ### ArrayList
> - **`addAll(Collection<? extends E> c)`**: Added fast path for 
> ArrayList-to-ArrayList copying using direct `System.arraycopy()` from 
> source's internal `elementData` array, eliminating intermediate `toArray()` 
> allocation
> 
> ### Collections.SingletonSet
> - **`toArray()`**: Direct implementation returning `new Object[] {element}`
> - **`toArray(T[] a)`**: Direct implementation with proper array sizing and 
> null termination per Collection contract
> 
> ## Performance Impact
> 
> | Class | Method | Size | Baseline | Optimized | Improvement |
> |-------|--------|------|----------|-----------|-------------|
> | ArrayList | addAll | 0 | 10.149 ns/op, 40 B/op | 3.929 ns/op, 24 B/op | 
> **61% faster, 40% less allocation** |
> | ArrayList | addAll | 5 | 23.804 ns/op, 104 B...

test/micro/org/openjdk/bench/java/util/ArrayListBulkOpsBenchmark.java line 120:

> 118:         ArrayList<String> result = new ArrayList<>(75);
> 119:         result.addAll(linkedListSource75);
> 120:         bh.consume(result);

No need for blackholes, just return the result, it has the same effect I 
believe.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/28116#discussion_r2489936317

Reply via email to