On Mon, 10 Aug 2026 18:51:46 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: There are up to four lazily allocated pools 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 four pools, each of size 64 
>> bytes.  The pool sizes are 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. As there can be up to four pools per 
>> thread, nested confined arenas are supported (i.e., up to four nested 
>> arenas).
>> 
>> ## 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...
>
> Per Minborg 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 46 additional 
> commits since the last revision:
> 
>  - Refactor the solution
>  - Merge branch 'master' into rfe-cached-arena-ofconfined-clean
>  - Add local pools
>  - Add 4 nested levels
>  - Merge branch 'master' into rfe-cached-arena-ofconfined-clean
>  - Clean up
>  - Remove directive
>  - Add slot config
>  - Add comment
>  - Simplify
>  - ... and 36 more: https://git.openjdk.org/jdk/compare/6398f081...1e3b71b6

One thing to think about is whether we should free pools that are not properly 
closed (i.e., pools that have a negative value) in the platform thread's cache. 
While this looks like a reasonable safety net, it might be the case that native 
code is using the address of an unclosed memory segment and that the arena was 
deliberately not closed.

So, one direction would be to retain the "favour leak over use-after-free" 
behavior that an `Arena` has today. This would mean we only free pools from 
properly closed arenas. This would also have the advantage that the behavior 
and handling would be the same for PTs and VTs.

This would also mean we could get rid of the signed address invariant we are 
relying on today.

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

PR Comment: https://git.openjdk.org/jdk/pull/31365#issuecomment-5277727372

Reply via email to