8224659: Parallel GC: Use WorkGang (1: PCRefProcTask)

Reviewed-by: stefank, kbarrett, tschatzl
This commit is contained in:
Leo Korinth 2019-08-16 09:18:19 +02:00
parent b84ffae32f
commit 3a38bec5ae
8 changed files with 94 additions and 82 deletions

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -123,6 +123,9 @@ jint ParallelScavengeHeap::initialize() {
return JNI_ENOMEM;
}
// Set up WorkGang
_workers.initialize_workers();
return JNI_OK;
}

@ -37,6 +37,7 @@
#include "gc/shared/referenceProcessor.hpp"
#include "gc/shared/softRefPolicy.hpp"
#include "gc/shared/strongRootsScope.hpp"
#include "gc/shared/workgroup.hpp"
#include "logging/log.hpp"
#include "memory/metaspace.hpp"
#include "utilities/growableArray.hpp"
@ -78,6 +79,8 @@ class ParallelScavengeHeap : public CollectedHeap {
MemoryPool* _survivor_pool;
MemoryPool* _old_pool;
WorkGang _workers;
virtual void initialize_serviceability();
void trace_heap(GCWhen::Type when, const GCTracer* tracer);
@ -99,7 +102,11 @@ class ParallelScavengeHeap : public CollectedHeap {
_old_manager(NULL),
_eden_pool(NULL),
_survivor_pool(NULL),
_old_pool(NULL) { }
_old_pool(NULL),
_workers("GC Thread",
ParallelGCThreads,
true /* are_GC_task_threads */,
false /* are_ConcurrentGC_threads */) { }
// For use by VM operations
enum CollectionType {
@ -252,6 +259,10 @@ class ParallelScavengeHeap : public CollectedHeap {
GCMemoryManager* old_gc_manager() const { return _old_manager; }
GCMemoryManager* young_gc_manager() const { return _young_manager; }
WorkGang& workers() {
return _workers;
}
};
// Class that can be used to print information about the

@ -130,48 +130,6 @@ void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) {
}
//
// RefProcTaskProxy
//
void RefProcTaskProxy::do_it(GCTaskManager* manager, uint which)
{
assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc");
ParCompactionManager* cm =
ParCompactionManager::gc_thread_compaction_manager(which);
PCMarkAndPushClosure mark_and_push_closure(cm);
ParCompactionManager::FollowStackClosure follow_stack_closure(cm);
_rp_task.work(_work_id, *PSParallelCompact::is_alive_closure(),
mark_and_push_closure, follow_stack_closure);
}
//
// RefProcTaskExecutor
//
void RefProcTaskExecutor::execute(ProcessTask& task, uint ergo_workers)
{
ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
uint active_gc_threads = heap->gc_task_manager()->active_workers();
assert(active_gc_threads == ergo_workers,
"Ergonomically chosen workers (%u) must be equal to active workers (%u)",
ergo_workers, active_gc_threads);
OopTaskQueueSet* qset = ParCompactionManager::stack_array();
TaskTerminator terminator(active_gc_threads, qset);
GCTaskQueue* q = GCTaskQueue::create();
for(uint i=0; i<active_gc_threads; i++) {
q->enqueue(new RefProcTaskProxy(task, i));
}
if (task.marks_oops_alive() && (active_gc_threads>1)) {
for (uint j=0; j<active_gc_threads; j++) {
q->enqueue(new StealMarkingTask(terminator.terminator()));
}
}
PSParallelCompact::gc_task_manager()->execute_and_wait(q);
}
//
// StealMarkingTask
//

@ -110,40 +110,6 @@ class MarkFromRootsTask : public GCTask {
virtual void do_it(GCTaskManager* manager, uint which);
};
//
// RefProcTaskProxy
//
// This task is used as a proxy to parallel reference processing tasks .
//
class RefProcTaskProxy : public GCTask {
typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
ProcessTask & _rp_task;
uint _work_id;
public:
RefProcTaskProxy(ProcessTask & rp_task, uint work_id)
: _rp_task(rp_task),
_work_id(work_id)
{ }
private:
virtual char* name() { return (char *)"Process referents by policy in parallel"; }
virtual void do_it(GCTaskManager* manager, uint which);
};
//
// RefProcTaskExecutor
//
// Task executor is an interface for the reference processor to run
// tasks using GCTaskManager.
//
class RefProcTaskExecutor: public AbstractRefProcTaskExecutor {
virtual void execute(ProcessTask& task, uint ergo_workers);
};
//
// StealMarkingTask

@ -44,6 +44,7 @@ class ParCompactionManager : public CHeapObj<mtGC> {
friend class UpdateAndFillClosure;
friend class RefProcTaskExecutor;
friend class IdleGCTask;
friend class PCRefProcTask;
public:

@ -55,6 +55,7 @@
#include "gc/shared/referenceProcessorPhaseTimes.hpp"
#include "gc/shared/spaceDecorator.hpp"
#include "gc/shared/weakProcessor.hpp"
#include "gc/shared/workerPolicy.hpp"
#include "logging/log.hpp"
#include "memory/iterator.inline.hpp"
#include "memory/resourceArea.hpp"
@ -1789,6 +1790,12 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
ResourceMark rm;
HandleMark hm;
const uint active_workers =
WorkerPolicy::calc_active_workers(ParallelScavengeHeap::heap()->workers().total_workers(),
ParallelScavengeHeap::heap()->workers().active_workers(),
Threads::number_of_non_daemon_threads());
ParallelScavengeHeap::heap()->workers().update_active_workers(active_workers);
// Set the number of GC threads to be used in this collection
gc_task_manager()->set_active_gang();
gc_task_manager()->task_idle_workers();
@ -2089,6 +2096,66 @@ public:
}
};
static void steal_marking_work(ParallelTaskTerminator& terminator, uint worker_id) {
assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc");
ParCompactionManager* cm =
ParCompactionManager::gc_thread_compaction_manager(worker_id);
oop obj = NULL;
ObjArrayTask task;
do {
while (ParCompactionManager::steal_objarray(worker_id, task)) {
cm->follow_array((objArrayOop)task.obj(), task.index());
cm->follow_marking_stacks();
}
while (ParCompactionManager::steal(worker_id, obj)) {
cm->follow_contents(obj);
cm->follow_marking_stacks();
}
} while (!terminator.offer_termination());
}
class PCRefProcTask : public AbstractGangTask {
typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
ProcessTask& _task;
uint _ergo_workers;
TaskTerminator _terminator;
public:
PCRefProcTask(ProcessTask& task, uint ergo_workers) :
AbstractGangTask("PCRefProcTask"),
_task(task),
_ergo_workers(ergo_workers),
_terminator(_ergo_workers, ParCompactionManager::stack_array()) {
}
virtual void work(uint worker_id) {
ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc");
ParCompactionManager* cm =
ParCompactionManager::gc_thread_compaction_manager(worker_id);
PCMarkAndPushClosure mark_and_push_closure(cm);
ParCompactionManager::FollowStackClosure follow_stack_closure(cm);
_task.work(worker_id, *PSParallelCompact::is_alive_closure(),
mark_and_push_closure, follow_stack_closure);
steal_marking_work(*_terminator.terminator(), worker_id);
}
};
class RefProcTaskExecutor: public AbstractRefProcTaskExecutor {
void execute(ProcessTask& process_task, uint ergo_workers) {
assert(ParallelScavengeHeap::heap()->workers().active_workers() == ergo_workers,
"Ergonomically chosen workers (%u) must be equal to active workers (%u)",
ergo_workers, ParallelScavengeHeap::heap()->workers().active_workers());
PCRefProcTask task(process_task, ergo_workers);
ParallelScavengeHeap::heap()->workers().run_task(&task);
}
};
void PSParallelCompact::marking_phase(ParCompactionManager* cm,
bool maximum_heap_compaction,
ParallelOldTracer *gc_tracer) {

@ -47,6 +47,7 @@
#include "gc/shared/referenceProcessorPhaseTimes.hpp"
#include "gc/shared/spaceDecorator.hpp"
#include "gc/shared/weakProcessor.hpp"
#include "gc/shared/workerPolicy.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "logging/log.hpp"
@ -339,15 +340,20 @@ bool PSScavenge::invoke_no_policy() {
// straying into the promotion labs.
HeapWord* old_top = old_gen->object_space()->top();
const uint active_workers =
WorkerPolicy::calc_active_workers(ParallelScavengeHeap::heap()->workers().total_workers(),
ParallelScavengeHeap::heap()->workers().active_workers(),
Threads::number_of_non_daemon_threads());
ParallelScavengeHeap::heap()->workers().update_active_workers(active_workers);
// Release all previously held resources
gc_task_manager()->release_all_resources();
// Set the number of GC threads to be used in this collection
gc_task_manager()->set_active_gang();
gc_task_manager()->task_idle_workers();
// Get the active number of workers here and use that value
// throughout the methods.
uint active_workers = gc_task_manager()->active_workers();
assert(active_workers == gc_task_manager()->active_workers(), "sanity, taskmanager and workgang ought to agree");
PSPromotionManager::pre_scavenge();

@ -56,7 +56,7 @@ public class TestInitialGCThreadLogging {
if (GC.Parallel.isSupported()) {
noneGCSupported = false;
testInitialGCThreadLogging("UseParallelGC", "ParGC Thread");
testInitialGCThreadLogging("UseParallelGC", "GC Thread");
}
if (GC.Shenandoah.isSupported()) {