This commit is contained in:
Jon Masamitsu 2016-07-29 20:23:24 +00:00
commit 3d74c4955e
12 changed files with 53 additions and 23 deletions

View File

@ -2888,7 +2888,10 @@ void CMSCollector::checkpointRootsInitialWork() {
CMSParInitialMarkTask tsk(this, &srs, n_workers);
initialize_sequential_subtasks_for_young_gen_rescan(n_workers);
if (n_workers > 1) {
// If the total workers is greater than 1, then multiple workers
// may be used at some time and the initialization has been set
// such that the single threaded path cannot be used.
if (workers->total_workers() > 1) {
workers->run_task(&tsk);
} else {
tsk.work(0);
@ -3507,7 +3510,7 @@ bool CMSCollector::do_marking_mt() {
uint num_workers = AdaptiveSizePolicy::calc_active_conc_workers(conc_workers()->total_workers(),
conc_workers()->active_workers(),
Threads::number_of_non_daemon_threads());
conc_workers()->set_active_workers(num_workers);
num_workers = conc_workers()->update_active_workers(num_workers);
CompactibleFreeListSpace* cms_space = _cmsGen->cmsSpace();

View File

@ -898,7 +898,7 @@ void ParNewGeneration::collect(bool full,
AdaptiveSizePolicy::calc_active_workers(workers->total_workers(),
workers->active_workers(),
Threads::number_of_non_daemon_threads());
workers->set_active_workers(active_workers);
active_workers = workers->update_active_workers(active_workers);
_old_gen = gch->old_gen();
// If the next generation is too full to accommodate worst-case promotion
@ -952,7 +952,9 @@ void ParNewGeneration::collect(bool full,
// separate thread causes wide variance in run times. We can't help this
// in the multi-threaded case, but we special-case n=1 here to get
// repeatable measurements of the 1-thread overhead of the parallel code.
if (active_workers > 1) {
// Might multiple workers ever be used? If yes, initialization
// has been done such that the single threaded path should not be used.
if (workers->total_workers() > 1) {
workers->run_task(&tsk);
} else {
tsk.work(0);

View File

@ -1331,7 +1331,7 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc,
AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(),
workers()->active_workers(),
Threads::number_of_non_daemon_threads());
workers()->set_active_workers(n_workers);
workers()->update_active_workers(n_workers);
ParRebuildRSTask rebuild_rs_task(this);
workers()->run_task(&rebuild_rs_task);
@ -3067,7 +3067,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
uint active_workers = AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(),
workers()->active_workers(),
Threads::number_of_non_daemon_threads());
workers()->set_active_workers(active_workers);
workers()->update_active_workers(active_workers);
TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
TraceMemoryManagerStats tms(false /* fullGC */, gc_cause());

View File

@ -1031,11 +1031,14 @@ void G1ConcurrentMark::mark_from_roots() {
uint active_workers = MAX2(1U, parallel_marking_threads());
assert(active_workers > 0, "Should have been set");
// Setting active workers is not guaranteed since fewer
// worker threads may currently exist and more may not be
// available.
active_workers = _parallel_workers->update_active_workers(active_workers);
// Parallel task terminator is set in "set_concurrency_and_phase()"
set_concurrency_and_phase(active_workers, true /* concurrent */);
G1CMConcurrentMarkingTask markingTask(this, cmThread());
_parallel_workers->set_active_workers(active_workers);
_parallel_workers->run_task(&markingTask);
print_stats();
}

View File

@ -537,7 +537,7 @@ void GCTaskManager::task_idle_workers() {
created_workers() - active_workers() - idle_workers();
if (more_inactive_workers < 0) {
int reduced_active_workers = active_workers() + more_inactive_workers;
set_active_workers(reduced_active_workers);
update_active_workers(reduced_active_workers);
more_inactive_workers = 0;
}
log_trace(gc, task)("JT: %d workers %d active %d idle %d more %d",

View File

@ -457,11 +457,12 @@ protected:
uint workers() const {
return _workers;
}
void set_active_workers(uint v) {
uint update_active_workers(uint v) {
assert(v <= _workers, "Trying to set more workers active than there are");
_active_workers = MIN2(v, _workers);
assert(v != 0, "Trying to set active workers to 0");
_active_workers = MAX2(1U, _active_workers);
return _active_workers;
}
// Sets the number of threads that will be used in a collection
void set_active_gang();

View File

@ -391,11 +391,15 @@ bool PSScavenge::invoke_no_policy() {
ParallelTaskTerminator terminator(
active_workers,
(TaskQueueSetSuper*) promotion_manager->stack_array_depth());
if (active_workers > 1) {
for (uint j = 0; j < active_workers; j++) {
q->enqueue(new StealTask(&terminator));
// If active_workers can exceed 1, add a StrealTask.
// PSPromotionManager::drain_stacks_depth() does not fully drain its
// stacks and expects a StealTask to complete the draining if
// ParallelGCThreads is > 1.
if (gc_task_manager()->workers() > 1) {
for (uint j = 0; j < active_workers; j++) {
q->enqueue(new StealTask(&terminator));
}
}
}
gc_task_manager()->execute_and_wait(q);
}

View File

@ -55,18 +55,29 @@ class WorkerManager : public AllStatic {
uint start = created_workers;
uint end = MIN2(active_workers, total_workers);
for (uint worker_id = start; worker_id < end; worker_id += 1) {
WorkerThread* new_worker = holder->install_worker(worker_id);
assert(new_worker != NULL, "Failed to allocate GangWorker");
WorkerThread* new_worker = NULL;
if (initializing || !InjectGCWorkerCreationFailure) {
new_worker = holder->install_worker(worker_id);
}
if (new_worker == NULL || !os::create_thread(new_worker, worker_type)) {
if (initializing) {
vm_exit_out_of_memory(0, OOM_MALLOC_ERROR,
"Cannot create worker GC thread. Out of system resources.");
log_trace(gc, task)("WorkerManager::add_workers() : "
"creation failed due to failed allocation of native %s",
new_worker == NULL ? "memory" : "thread");
if (new_worker != NULL) {
delete new_worker;
}
if (initializing) {
vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create worker GC thread. Out of system resources.");
}
break;
}
created_workers++;
os::start_thread(new_worker);
}
log_trace(gc, task)("WorkerManager::add_workers() : "
"created_workers: %u", created_workers);
return created_workers;
}

View File

@ -274,8 +274,10 @@ void WorkGang::run_task(AbstractGangTask* task, uint num_workers) {
"Trying to execute task %s with %u workers which is more than the amount of total workers %u.",
task->name(), num_workers, total_workers());
guarantee(num_workers > 0, "Trying to execute task %s with zero workers", task->name());
add_workers(num_workers, false);
uint old_num_workers = _active_workers;
update_active_workers(num_workers);
_dispatcher->coordinator_execute_on_workers(task, num_workers);
update_active_workers(old_num_workers);
}
AbstractGangWorker::AbstractGangWorker(AbstractWorkGang* gang, uint id) {

View File

@ -156,15 +156,14 @@ class AbstractWorkGang : public CHeapObj<mtInternal> {
return _active_workers;
}
void set_active_workers(uint v) {
uint update_active_workers(uint v) {
assert(v <= _total_workers,
"Trying to set more workers active than there are");
_active_workers = MIN2(v, _total_workers);
add_workers(false /* exit_on_failure */);
assert(v != 0, "Trying to set active workers to 0");
assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers,
"Unless dynamic should use total workers");
log_info(gc, task)("GC Workers: using %d out of %d", _active_workers, _total_workers);
return _active_workers;
}
// Add GC workers as needed.

View File

@ -1438,6 +1438,10 @@ public:
"Dynamically choose the number of parallel threads " \
"parallel gc will use") \
\
diagnostic(bool, InjectGCWorkerCreationFailure, false, \
"Inject thread creation failures for " \
"UseDynamicNumberOfGCThreads") \
\
diagnostic(bool, ForceDynamicNumberOfGCThreads, false, \
"Force dynamic selection of the number of " \
"parallel threads parallel gc will use to aid debugging") \

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2016, 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
@ -33,6 +33,7 @@
* @run main/othervm -Xmx384M -XX:+UseConcMarkSweepGC TestGCOld 50 1 20 10 10000
* @run main/othervm -Xmx384M -XX:+UseG1GC TestGCOld 50 1 20 10 10000
* @run main/othervm -Xms64m -Xmx128m -XX:+UseG1GC -XX:+UseDynamicNumberOfGCThreads -Xlog:gc,gc+task=trace TestGCOld 50 5 20 1 5000
* @run main/othervm -Xms64m -Xmx128m -XX:+UseG1GC -XX:+UseDynamicNumberOfGCThreads -XX:+UnlockDiagnosticVMOptions -XX:+InjectGCWorkerCreationFailure -Xlog:gc,gc+task=trace TestGCOld 50 5 20 1 5000
*/
import java.text.*;