8224659: Parallel GC: Use WorkGang (1: PCRefProcTask)
Reviewed-by: stefank, kbarrett, tschatzl
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Fri Aug 16 08:42:09 2019 +0800
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Fri Aug 16 09:18:19 2019 +0200
@@ -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 @@
return JNI_ENOMEM;
}
+ // Set up WorkGang
+ _workers.initialize_workers();
+
return JNI_OK;
}
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp Fri Aug 16 08:42:09 2019 +0800
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp Fri Aug 16 09:18:19 2019 +0200
@@ -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 @@
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 @@
_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 @@
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
--- a/src/hotspot/share/gc/parallel/pcTasks.cpp Fri Aug 16 08:42:09 2019 +0800
+++ b/src/hotspot/share/gc/parallel/pcTasks.cpp Fri Aug 16 09:18:19 2019 +0200
@@ -131,48 +131,6 @@
//
-// 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
//
--- a/src/hotspot/share/gc/parallel/pcTasks.hpp Fri Aug 16 08:42:09 2019 +0800
+++ b/src/hotspot/share/gc/parallel/pcTasks.hpp Fri Aug 16 09:18:19 2019 +0200
@@ -110,40 +110,6 @@
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
--- a/src/hotspot/share/gc/parallel/psCompactionManager.hpp Fri Aug 16 08:42:09 2019 +0800
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.hpp Fri Aug 16 09:18:19 2019 +0200
@@ -44,6 +44,7 @@
friend class UpdateAndFillClosure;
friend class RefProcTaskExecutor;
friend class IdleGCTask;
+ friend class PCRefProcTask;
public:
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp Fri Aug 16 08:42:09 2019 +0800
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp Fri Aug 16 09:18:19 2019 +0200
@@ -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 @@
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 @@
}
};
+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) {
--- a/src/hotspot/share/gc/parallel/psScavenge.cpp Fri Aug 16 08:42:09 2019 +0800
+++ b/src/hotspot/share/gc/parallel/psScavenge.cpp Fri Aug 16 09:18:19 2019 +0200
@@ -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 @@
// 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();
--- a/test/hotspot/jtreg/gc/ergonomics/TestInitialGCThreadLogging.java Fri Aug 16 08:42:09 2019 +0800
+++ b/test/hotspot/jtreg/gc/ergonomics/TestInitialGCThreadLogging.java Fri Aug 16 09:18:19 2019 +0200
@@ -56,7 +56,7 @@
if (GC.Parallel.isSupported()) {
noneGCSupported = false;
- testInitialGCThreadLogging("UseParallelGC", "ParGC Thread");
+ testInitialGCThreadLogging("UseParallelGC", "GC Thread");
}
if (GC.Shenandoah.isSupported()) {