8224659: Parallel GC: Use WorkGang (1: PCRefProcTask)
Reviewed-by: stefank, kbarrett, tschatzl
This commit is contained in:
parent
b84ffae32f
commit
3a38bec5ae
src/hotspot/share/gc/parallel
parallelScavengeHeap.cppparallelScavengeHeap.hpppcTasks.cpppcTasks.hpppsCompactionManager.hpppsParallelCompact.cpppsScavenge.cpp
test/hotspot/jtreg/gc/ergonomics
@ -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()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user