RFR: 8371260: Improve scaling of downcalls using MemorySegments allocated with shared arenas.
Alan Bateman
alanb at openjdk.org
Mon Dec 1 13:20:49 UTC 2025
On Mon, 1 Dec 2025 11:59:38 GMT, Stuart Monteith <smonteith at openjdk.org> wrote:
> MemorySegments allocated from shared Arena from
> java.lang.foreign.Arena.ofShared() have their lifecycle controlled by jdk.internal.foreign.SharedSession. This class ensures that the MemorySegments can't be freed until after a thread has called Arena.close(). This is implemented using a counter that is atomically incremented when used, and decremented when not used, on every invocation of a downcall. While shared Arenas allow any thread to use it and to close it, this tracking has a cost when multiple threads are contended on it. This patch changes the implementation to use multiple counters to reduce contention. sun.nio.ch.IOUtil, java.nio.Buffer and sun.nio.ch.SimpleAsynchronousFileChannelImpl are modified as they have threads releasing the scope different from the ones that allocated them, so a ticket that tracks the counter has to be passed over.
>
> The microbenchmark org.openjdk.bench.java.lang.foreign. CallOverheadConstant.panama_identity_memory_address_shared_3 was used to generate the following results. The scalability was checked on a number of platforms with the JMH parameter "-t" specifying the number of threads. Measurements are in ns/op .
>
> The hardware are the Neoverse-N1, N2, V1 and V2, Intel Xeon 8375c and the AMD Epyc 9654.
>
> | Threads | N1 | N2 | V1 | V2 | Xeon | Epyc |
> |---------|-------|-------|-------|-------|-------|-------|
> | 1 | 30.88 | 32.15 | 33.54 | 32.82 | 27.46 | 8.45 |
> | 2 | 142.56 | 134.48 | 132.01 | 131.50 | 116.68 | 46.53 |
> | 4 | 310.18 | 282.75 | 287.59 | 271.82 | 251.88 | 86.11 |
> | 8 | 702.02 | 710.29 | 736.72 | 670.63 | 533.46 | 194.60 |
> | 16 | 1,436.17 | 1,684.80 | 1,833.69 | 1,782.78 | 1,100.15 | 827.28 |
> | 24 | 2,185.55 | 2,508.86 | 2,732.22 | 2,815.26 | 1,646.09 | 1,530.28 |
> | 32 | 2,942.48 | 3,432.84 | 3,643.64 | 3,782.23 | 2,236.81 | 2,278.52 |
> | 48 | 4,466.56 | 5,174.72 | 5,401.95 | 5,621.41 | 4,926.30 | 3,026.58 |
>
> After:
>
> | Threads | N1 | N2 | V1 | V2 | Xeon | Epyc |
> |---------|-------|-------|-------|-------|-------|-------|
> | 1 | 32.41 | 32.11 | 34.43 | 31.32 | 27.94 | 9.82 |
> | 2 | 32.64 | 33.72 | 35.11 | 31.30 | 28.02 | 9.81 |
> | 4 | 32.71 | 36.84 | 34.67 | 31.35 | 28.12 | 10.49 |
> | 8 | 58.22 | 31.60 | 36.87 | 31.72 | 47.09 |...
src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java line 396:
> 394: private final PendingFuture<Integer,A> result;
> 395: private volatile boolean released;
> 396: private int ticket; // to release buffer scope
This is for substitution, so needs to be declared with buf (further down), and needs to be volatile (can't use plain access as it may be released on different thread).
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/28575#discussion_r2577021290
More information about the security-dev
mailing list