RFR: JDK-8260332: ParallelGC: Cooperative pretouch for oldgen expansion [v2]

David Holmes dholmes at openjdk.java.net
Sun Mar 14 21:42:08 UTC 2021


On Sun, 14 Mar 2021 13:27:26 GMT, Amit Pawar <github.com+71302734+amitdpawar at openjdk.org> wrote:

>> In case of ParallelGC, oldgen expansion can happen during promotion. Expanding thread will touch the pages and can't request for task execution as this GC thread is already executing a task. The expanding thread holds the lock on "ExpandHeap_lock" to resize the oldgen and other threads may wait for their turn. This is a blocking call.
>> 
>> This patch changes this behavior by adding another constructor in "MutexLocker" class to enable non blocking or try_lock operation. This way one thread will acquire the lock and other threads can join pretouch work. Threads failed to acquire the lock will join pretouch only when task is marked ready by expanding thread.
>> 
>> Following minimum expansion size are seen during expansion.
>> 1. 512KB without largepages and without UseNUMA.
>> 2. 64MB without largepages and with UseNUMA,
>> 3. 2MB (on x86)  with large pages and without UseNUMA,
>> 4. 64MB without large pages and with UseNUMA.
>> 
>> When Oldgen is expanding repeatedly with smaller size then this change wont help. For such cases, resize size should adapt to application demand to make use of this change. For example if application nature triggers 100 expansion with smaller sizes in same GC then it is better to increase the expansion size during each resize to reduce the number of resizes. If this patch is accepted then will plan to fix this case in another patch.
>> 
>> Jtreg all test passed.
>> 
>> Please review this change.
>
> Amit Pawar has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Fixed build issues for some targets and updated with suggested changes.

src/hotspot/share/gc/shared/pretouchTask.cpp line 96:

> 94:     Atomic::release_store(&_cur_addr, _end_addr);
> 95:     OrderAccess::storestore();
> 96:     set_task_done();

The storestore barrier is not needed as the set_task_done() is a release_store which already has a storestore barrier.

src/hotspot/share/gc/shared/pretouchTask.cpp line 56:

> 54: void PretouchTask::reinitialize(char* start_addr, char* end_addr) {
> 55:   Atomic::release_store(&_cur_addr, start_addr);
> 56:   Atomic::release_store(&_end_addr, end_addr);

Back-to-back release-stores have redundant loadstore semantics. You could just use a storestore() barrier after the first release_store, then use plain Atomic::store for the second field.

src/hotspot/share/gc/parallel/mutableSpace.cpp line 149:

> 147:         // waiting to expand old-gen will join from PSOldGen::expand_for_allocate
> 148:         // function for pretouch work.
> 149:         pretouch_task->set_task_ready();

The storestore is not needed as it is included in the release_store of set_task_ready().

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

PR: https://git.openjdk.java.net/jdk/pull/2976


More information about the hotspot-dev mailing list