On Fri, 17 Apr 2026 20:37:56 GMT, Dean Long <[email protected]> wrote:

>> The test `compiler/print/CompileCommandMemLimit.java` fails because we 
>> suddenly don't hit the expected memory limit anymore when compiling empty 
>> method `TestMain::method2` with `--enable-preview`. In fact, the VM is 
>> reporting that no memory is used for compilation at all:
>> 
>> c1 (27) (ok) Arena usage 
>> compiler/print/CompileCommandMemLimit$TestMain::method2(()V): Total Usage: 0
>> 
>> 
>> I added some logging to the 
>> `CompilationMemoryStatistic::on_arena_chunk_allocation` path in 
>> `ChunkPool::allocate_chunk` and noticed that the only difference is that 
>> with `--enable-preview` we don't have this allocation in 
>> `Thread::current()->resource_area()`:
>> 
>> V  [libjvm.so+0x4bb99c]  ChunkPool::allocate_chunk(Arena*, unsigned long, 
>> AllocFailStrategy::AllocFailEnum)+0x16c
>> V  [libjvm.so+0x4bc28d]  Arena::grow(unsigned long, 
>> AllocFailStrategy::AllocFailEnum)+0x5d
>> V  [libjvm.so+0x7a4d83]  
>> DebugInformationRecorder::DebugInformationRecorder(OopRecorder*)+0x43
>> V  [libjvm.so+0x58e3d1]  Compilation::initialize()+0xb1
>> V  [libjvm.so+0x58fe1c]  Compilation::compile_method()+0x6c
>> V  [libjvm.so+0x590190]  Compilation::Compilation(AbstractCompiler*, ciEnv*, 
>> ciMethod*, int, BufferBlob*, bool, DirectiveSet*)+0x1f0
>> V  [libjvm.so+0x590866]  Compiler::compile_method(ciEnv*, ciMethod*, int, 
>> bool, DirectiveSet*)+0xb6
>> 
>> 
>> The reason is that with `--enable-preview` -> `-XX:+UseFieldFlattening` we 
>> have a new code path `ciInstanceKlass::compute_nonstatic_fields_impl` that 
>> processes flat fields and creates `ciField` objects for those. We hit that 
>> code path very early during `ciObjectFactory::init_shared_objects` for some 
>> core-libs klass:
>> 
>> 
>> V  [libjvm.so+0x4bb99c]  ChunkPool::allocate_chunk(Arena*, unsigned long, 
>> AllocFailStrategy::AllocFailEnum)+0x16c
>> V  [libjvm.so+0x4bc28d]  Arena::grow(unsigned long, 
>> AllocFailStrategy::AllocFailEnum)+0x5d
>> V  [libjvm.so+0x10bfdce]  Symbol::as_C_string() const+0x1e
>> V  [libjvm.so+0x69da5c]  ciField::ciField(ciField*, ciField*)+0x7c
>> V  [libjvm.so+0x6a6ab8]  
>> ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray<ciField*> 
>> const*, GrowableArray<ciField*> const*)+0x1168
>> V  [libjvm.so+0x6bb22c]  ciObjectFactory::init_shared_objects()+0xc8c
>> V  [libjvm.so+0x6bcc56]  ciObjectFactory::initialize()+0x96
>> V  [libjvm.so+0x759535]  CompileBroker::compiler_thread_loop()+0x1a5
>> ``` 
>> 
>> As a result, the `Thread::current()->resource_area()` is growing already 
>> before the allocation and there is no need to grow it anymore during the 
>> compi...
>
> While adding missing ResourceMarks is good, this problem feels a little like 
> "whack-a-mole".  Also, there seems to be opposing tension between memory stat 
> accuracy and arena efficiency.  For efficiency, it seems better if a 
> compilation rarely needs to allocate a new chunk.  On the other hand, for 
> chunk-based memory stats to work, it would be better if every compilation 
> needs to allocate a new chunk.  For a long-term solution, I think we need 
> some sort of "reset" after init_shared_objects() if MemLimit is enabled.  My 
> first thought was to split the current chunk, but that complicates freeing.  
> My second thought was some kind of high water mark.  Or maybe it is enough to 
> use smaller chunk sizes for compiler threads when MemLimit is enabled?

@dean-long Thanks for looking at this! I thought about this as well and I'm not 
sure if that extra complexity is worth it. The CI will only be initialized once 
by the first compiler thread that reaches there and even then, 
`init_shared_objects` should only increase the hwm of the resource arena 
insignificantly (given that the right ResourceMarks are in place). The memory 
consumption of the actual compilation that we want to measure should greatly 
outweigh this, right?

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

PR Comment: https://git.openjdk.org/valhalla/pull/2330#issuecomment-4278218891

Reply via email to