On Thu, 18 Jun 2026 15:22:37 GMT, Per Minborg <[email protected]> wrote:

>> ## Summary
>> 
>> This PR proposes to introduce a pooled confined arena as an optimization for 
>> `Arena.ofConfined()`, where small native allocations can be served from a 
>> reusable per-thread/per-slot memory pool instead of calling the regular 
>> native allocator for every short-lived arena. The arena remains confined to 
>> its owner thread and is still closed normally, but its backing storage can 
>> be reset and reused when the arena closes. The feature requires no API 
>> changes.
>> 
>> ### Outline
>> 
>> Platform threads: one lazily allocated pool per Thread, encoded in 
>> `Thread.confinedMemoryPool`.
>> Virtual threads: fixed shared native pool with CAS-protected slots, because 
>> per-virtual-thread native pools would not scale.
>> 
>> Pooled memory is zeroed out upon _closing_ an Arena to minimize data 
>> visibility between reuse. This means the data is visible only within a TWR 
>> block, and never outside it.
>> 
>> By default, a confined arena has access to 64 bytes of pooled data.  The 
>> pool size is configurable via a system property and can be 8, 16, 32, or 64 
>> bytes. Pooling can also be turned off completely by setting the pool 
>> power-of-two size to zero. Nested confined arenas are not supported
>> 
>> ## Static Analysis
>> 
>> An extensive static corpus analysis of third-party libraries and the JDK 
>> itself has been conducted with respect to `Area.ofConfined()` usage, 
>> revealing that confined arenas were used _only_ in TWR blocks and _never_ in 
>> an unstructured way. The static analysis further revealed that in most 
>> cases, only a small amount of native memory was ever allocated, usually less 
>> than 32 bytes, and in many cases, 8 bytes or less. This usage pattern lends 
>> itself well to pooling. 
>> 
>> ## Dynamic Analysis
>> 
>> A dynamic statistical analysis of actual runs was also made, where various 
>> properties of confined arenas were recorded and summarized during a complete 
>> tier1 test run. While a tier1 run is not necessarily representative of a 
>> typical application workload, it provided some interesting results:
>> 
>> The run produced 93 per-process histogram blocks and 788,773,092 closed 
>> confined arenas. The result is dominated by arenas with no native allocation 
>> at all: 375,934,768 arenas (47.661%) are in the zero-byte bucket. Counting 
>> arenas up to 63 bytes covers 99.997% of all arena closures.
>> 
>> The largest count bucket is 8-15 bytes per arena with 400,951,293 arenas 
>> (50.832% of all arenas). The largest byte bucket is 8-15 bytes per arena 
>> with 3,207,623,039 B (3,059.03 MiB) (46.794% of all by...
>
> Per Minborg has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Improve performance for VTs

src/java.base/share/classes/jdk/internal/foreign/ConfinedSegmentPool.java line 
61:

> 59:     static final long POOLED_MEMORY_SIZE = 
> clampedPowerOfPropertyOr(POOLED_MEMORY_PROPERTY, 6);
> 60: 
> 61:     private static volatile boolean virtualPoolInitialized;

This should probably be kept `@Stable`, so that it can be constant folded once 
`VirtualThreadPool` is initialised:
Suggestion:

    @Stable
    private static volatile boolean virtualPoolInitialized;

src/java.base/share/classes/jdk/internal/foreign/ConfinedSegmentPool.java line 
374:

> 372:         private static long allocatePool() {
> 373:             return mallocAndZero(POOLED_MEMORY_SIZE * SLOTS);
> 374:         }

This should probably use a `POOL_OFFSET` in place of `POOLED_MEMORY_SIZE`, 
which would be computed as:

private static long poolOffset() {
        final int cacheLineSize = U.dataCacheLineFlushSize();
        return cacheLineSize > 0
                ? Math.max(cacheLineSize, POOLED_MEMORY_SIZE)
                : POOLED_MEMORY_SIZE; // No cache line support
}


So that adjacent virtual threads don’t needlessly touch each other’s cache 
lines.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/31365#discussion_r3437123896
PR Review Comment: https://git.openjdk.org/jdk/pull/31365#discussion_r3437159861

Reply via email to