# HG changeset patch # User tschatzl # Date 1508940789 -7200 # Node ID d011b1650071643802e7aad2f946d2c8ba5286b2 # Parent 75aa2a8e7304be592b529bc5012467b3a4e928f7 8189673: Consistent naming of concurrent threads, tasks and related identifiers Reviewed-by: sjohanss, drwhite diff -r 75aa2a8e7304 -r d011b1650071 src/hotspot/share/gc/g1/g1ConcurrentMark.cpp --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Wed Oct 25 16:12:15 2017 +0200 +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Wed Oct 25 16:13:09 2017 +0200 @@ -326,16 +326,19 @@ return true; } -uint G1ConcurrentMark::scale_parallel_threads(uint n_par_threads) { - return MAX2((n_par_threads + 2) / 4, 1U); +// Returns the maximum number of workers to be used in a concurrent +// phase based on the number of GC workers being used in a STW +// phase. +static uint scale_concurrent_worker_threads(uint num_gc_workers) { + return MAX2((num_gc_workers + 2) / 4, 1U); } G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev_bitmap_storage, G1RegionToSpaceMapper* next_bitmap_storage) : _g1h(g1h), _mark_bitmap_1(), _mark_bitmap_2(), - _parallel_marking_threads(0), - _max_parallel_marking_threads(0), + _num_concurrent_workers(0), + _max_concurrent_workers(0), _cleanup_list("Concurrent Mark Cleanup List"), _prev_mark_bitmap(&_mark_bitmap_1), @@ -344,11 +347,11 @@ _global_mark_stack(), // _finger set in set_non_marking_state - _max_worker_id(ParallelGCThreads), + _max_num_tasks(ParallelGCThreads), // _active_tasks set in set_non_marking_state // _tasks set inside the constructor - _task_queues(new G1CMTaskQueueSet((int) _max_worker_id)), - _terminator(ParallelTaskTerminator((int) _max_worker_id, _task_queues)), + _task_queues(new G1CMTaskQueueSet((int) _max_num_tasks)), + _terminator(ParallelTaskTerminator((int) _max_num_tasks, _task_queues)), _has_overflown(false), _concurrent(false), @@ -368,7 +371,7 @@ _total_counting_time(0.0), _total_rs_scrub_time(0.0), - _parallel_workers(NULL), + _concurrent_workers(NULL), _completed_initialization(false) { @@ -390,37 +393,33 @@ _root_regions.init(_g1h->survivor(), this); + if (FLAG_IS_DEFAULT(ConcGCThreads) || ConcGCThreads == 0) { + // Calculate the number of concurrent worker threads by scaling + // the number of parallel GC threads. + uint marking_thread_num = scale_concurrent_worker_threads(ParallelGCThreads); + FLAG_SET_ERGO(uint, ConcGCThreads, marking_thread_num); + } + + assert(ConcGCThreads > 0, "ConcGCThreads have been set."); if (ConcGCThreads > ParallelGCThreads) { log_warning(gc)("More ConcGCThreads (%u) than ParallelGCThreads (%u).", ConcGCThreads, ParallelGCThreads); return; } - if (FLAG_IS_DEFAULT(ConcGCThreads) || ConcGCThreads == 0) { - // Calculate the number of parallel marking threads by scaling - // the number of parallel GC threads. - uint marking_thread_num = scale_parallel_threads(ParallelGCThreads); - FLAG_SET_ERGO(uint, ConcGCThreads, marking_thread_num); - } - - assert(ConcGCThreads > 0, "Should have been set"); log_debug(gc)("ConcGCThreads: %u", ConcGCThreads); log_debug(gc)("ParallelGCThreads: %u", ParallelGCThreads); - _parallel_marking_threads = ConcGCThreads; - _max_parallel_marking_threads = _parallel_marking_threads; - - _parallel_workers = new WorkGang("G1 Marker", _max_parallel_marking_threads, false, true); - if (_parallel_workers == NULL) { - vm_exit_during_initialization("Failed necessary allocation."); - } else { - _parallel_workers->initialize_workers(); - } + _num_concurrent_workers = ConcGCThreads; + _max_concurrent_workers = _num_concurrent_workers; + + _concurrent_workers = new WorkGang("G1 Conc", _max_concurrent_workers, false, true); + _concurrent_workers->initialize_workers(); if (FLAG_IS_DEFAULT(MarkStackSize)) { size_t mark_stack_size = MIN2(MarkStackSizeMax, - MAX2(MarkStackSize, (size_t) (_parallel_marking_threads * TASKQUEUE_SIZE))); + MAX2(MarkStackSize, (size_t) (_max_concurrent_workers * TASKQUEUE_SIZE))); // Verify that the calculated value for MarkStackSize is in range. // It would be nice to use the private utility routine from Arguments. if (!(mark_stack_size >= 1 && mark_stack_size <= MarkStackSizeMax)) { @@ -455,13 +454,13 @@ vm_exit_during_initialization("Failed to allocate initial concurrent mark overflow mark stack."); } - _tasks = NEW_C_HEAP_ARRAY(G1CMTask*, _max_worker_id, mtGC); - _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_worker_id, mtGC); + _tasks = NEW_C_HEAP_ARRAY(G1CMTask*, _max_num_tasks, mtGC); + _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_num_tasks, mtGC); // so that the assertion in MarkingTaskQueue::task_queue doesn't fail - _active_tasks = _max_worker_id; - - for (uint i = 0; i < _max_worker_id; ++i) { + _num_active_tasks = _max_num_tasks; + + for (uint i = 0; i < _max_num_tasks; ++i) { G1CMTaskQueue* task_queue = new G1CMTaskQueue(); task_queue->initialize(); _task_queues->register_queue(i, task_queue); @@ -495,7 +494,7 @@ // We reset all of them, since different phases will use // different number of active threads. So, it's easiest to have all // of them ready. - for (uint i = 0; i < _max_worker_id; ++i) { + for (uint i = 0; i < _max_num_tasks; ++i) { _tasks[i]->reset(_next_mark_bitmap); } @@ -516,16 +515,16 @@ clear_has_overflown(); _finger = _heap_start; - for (uint i = 0; i < _max_worker_id; ++i) { + for (uint i = 0; i < _max_num_tasks; ++i) { G1CMTaskQueue* queue = _task_queues->queue(i); queue->set_empty(); } } void G1ConcurrentMark::set_concurrency(uint active_tasks) { - assert(active_tasks <= _max_worker_id, "we should not have more"); - - _active_tasks = active_tasks; + assert(active_tasks <= _max_num_tasks, "we should not have more"); + + _num_active_tasks = active_tasks; // Need to update the three data structures below according to the // number of active threads for this phase. _terminator = ParallelTaskTerminator((int) active_tasks, _task_queues); @@ -538,7 +537,7 @@ _concurrent = concurrent; // We propagate this to all tasks, not just the active ones. - for (uint i = 0; i < _max_worker_id; ++i) { + for (uint i = 0; i < _max_num_tasks; ++i) { _tasks[i]->set_concurrent(concurrent); } @@ -559,7 +558,7 @@ // We set the global marking state to some default values when we're // not doing marking. reset_marking_state(); - _active_tasks = 0; + _num_active_tasks = 0; clear_concurrent_marking_in_progress(); } @@ -659,12 +658,12 @@ // is the case. guarantee(!_g1h->collector_state()->mark_in_progress(), "invariant"); - clear_bitmap(_next_mark_bitmap, _parallel_workers, true); + clear_bitmap(_next_mark_bitmap, _concurrent_workers, true); // Clear the live count data. If the marking has been aborted, the abort() // call already did that. if (!has_aborted()) { - clear_live_data(_parallel_workers); + clear_live_data(_concurrent_workers); DEBUG_ONLY(verify_live_data_clear()); } @@ -857,27 +856,25 @@ ~G1CMConcurrentMarkingTask() { } }; -// Calculates the number of active workers for a concurrent -// phase. -uint G1ConcurrentMark::calc_parallel_marking_threads() { - uint n_conc_workers = 0; +uint G1ConcurrentMark::calc_active_marking_workers() { + uint result = 0; if (!UseDynamicNumberOfGCThreads || (!FLAG_IS_DEFAULT(ConcGCThreads) && !ForceDynamicNumberOfGCThreads)) { - n_conc_workers = _max_parallel_marking_threads; + result = _max_concurrent_workers; } else { - n_conc_workers = - AdaptiveSizePolicy::calc_default_active_workers(_max_parallel_marking_threads, + result = + AdaptiveSizePolicy::calc_default_active_workers(_max_concurrent_workers, 1, /* Minimum workers */ - _parallel_marking_threads, + _num_concurrent_workers, Threads::number_of_non_daemon_threads()); - // Don't scale down "n_conc_workers" by scale_parallel_threads() because - // that scaling has already gone into "_max_parallel_marking_threads". + // Don't scale the result down by scale_concurrent_workers() because + // that scaling has already gone into "_max_concurrent_workers". } - assert(n_conc_workers > 0 && n_conc_workers <= _max_parallel_marking_threads, - "Calculated number of workers must be larger than zero and at most the maximum %u, but is %u", - _max_parallel_marking_threads, n_conc_workers); - return n_conc_workers; + assert(result > 0 && result <= _max_concurrent_workers, + "Calculated number of marking workers must be larger than zero and at most the maximum %u, but is %u", + _max_concurrent_workers, result); + return result; } void G1ConcurrentMark::scan_root_region(HeapRegion* hr) { @@ -925,17 +922,17 @@ if (root_regions()->scan_in_progress()) { assert(!has_aborted(), "Aborting before root region scanning is finished not supported."); - _parallel_marking_threads = MIN2(calc_parallel_marking_threads(), - // We distribute work on a per-region basis, so starting - // more threads than that is useless. - root_regions()->num_root_regions()); - assert(_parallel_marking_threads <= _max_parallel_marking_threads, + _num_concurrent_workers = MIN2(calc_active_marking_workers(), + // We distribute work on a per-region basis, so starting + // more threads than that is useless. + root_regions()->num_root_regions()); + assert(_num_concurrent_workers <= _max_concurrent_workers, "Maximum number of marking threads exceeded"); G1CMRootRegionScanTask task(this); log_debug(gc, ergo)("Running %s using %u workers for %u work units.", - task.name(), _parallel_marking_threads, root_regions()->num_root_regions()); - _parallel_workers->run_task(&task, _parallel_marking_threads); + task.name(), _num_concurrent_workers, root_regions()->num_root_regions()); + _concurrent_workers->run_task(&task, _num_concurrent_workers); // It's possible that has_aborted() is true here without actually // aborting the survivor scan earlier. This is OK as it's @@ -974,25 +971,21 @@ _restart_for_overflow = false; - // _g1h has _n_par_threads - _parallel_marking_threads = calc_parallel_marking_threads(); - assert(_parallel_marking_threads <= _max_parallel_marking_threads, - "Maximum number of marking threads exceeded"); - - uint active_workers = MAX2(1U, _parallel_marking_threads); - assert(active_workers > 0, "Should have been set"); + _num_concurrent_workers = calc_active_marking_workers(); + + uint active_workers = MAX2(1U, _num_concurrent_workers); // 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); - log_info(gc, task)("Using %u workers of %u for marking", active_workers, _parallel_workers->total_workers()); + active_workers = _concurrent_workers->update_active_workers(active_workers); + log_info(gc, task)("Using %u workers of %u for marking", active_workers, _concurrent_workers->total_workers()); // Parallel task terminator is set in "set_concurrency_and_phase()" set_concurrency_and_phase(active_workers, true /* concurrent */); G1CMConcurrentMarkingTask marking_task(this, cm_thread()); - _parallel_workers->run_task(&marking_task); + _concurrent_workers->run_task(&marking_task); print_stats(); } @@ -1604,7 +1597,7 @@ // we utilize all the worker threads we can. bool processing_is_mt = rp->processing_is_mt(); uint active_workers = (processing_is_mt ? g1h->workers()->active_workers() : 1U); - active_workers = MAX2(MIN2(active_workers, _max_worker_id), 1U); + active_workers = MAX2(MIN2(active_workers, _max_num_tasks), 1U); // Parallel processing task executor. G1CMRefProcTaskExecutor par_task_executor(g1h, this, @@ -1909,7 +1902,7 @@ _global_mark_stack.iterate(VerifyNoCSetOops("Stack")); // Verify entries on the task queues - for (uint i = 0; i < _max_worker_id; ++i) { + for (uint i = 0; i < _max_num_tasks; ++i) { G1CMTaskQueue* queue = _task_queues->queue(i); queue->iterate(VerifyNoCSetOops("Queue", i)); } @@ -1926,8 +1919,8 @@ } // Verify the task fingers - assert(_parallel_marking_threads <= _max_worker_id, "sanity"); - for (uint i = 0; i < _parallel_marking_threads; ++i) { + assert(_num_concurrent_workers <= _max_num_tasks, "sanity"); + for (uint i = 0; i < _num_concurrent_workers; ++i) { G1CMTask* task = _tasks[i]; HeapWord* task_finger = task->finger(); if (task_finger != NULL && task_finger < _heap_end) { @@ -1942,7 +1935,7 @@ } #endif // PRODUCT void G1ConcurrentMark::create_live_data() { - _g1h->g1_rem_set()->create_card_live_data(_parallel_workers, _next_mark_bitmap); + _g1h->g1_rem_set()->create_card_live_data(_concurrent_workers, _next_mark_bitmap); } void G1ConcurrentMark::finalize_live_data() { @@ -1968,7 +1961,7 @@ return; } log_debug(gc, stats)("---------------------------------------------------------------------"); - for (size_t i = 0; i < _active_tasks; ++i) { + for (size_t i = 0; i < _num_active_tasks; ++i) { _tasks[i]->print_stats(); log_debug(gc, stats)("---------------------------------------------------------------------"); } @@ -2000,7 +1993,7 @@ }) // Empty mark stack reset_marking_state(); - for (uint i = 0; i < _max_worker_id; ++i) { + for (uint i = 0; i < _max_num_tasks; ++i) { _tasks[i]->clear_region_fields(); } _first_overflow_barrier_sync.abort(); @@ -2054,11 +2047,11 @@ } void G1ConcurrentMark::print_worker_threads_on(outputStream* st) const { - _parallel_workers->print_worker_threads_on(st); + _concurrent_workers->print_worker_threads_on(st); } void G1ConcurrentMark::threads_do(ThreadClosure* tc) const { - _parallel_workers->threads_do(tc); + _concurrent_workers->threads_do(tc); } void G1ConcurrentMark::print_on_error(outputStream* st) const { diff -r 75aa2a8e7304 -r d011b1650071 src/hotspot/share/gc/g1/g1ConcurrentMark.hpp --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp Wed Oct 25 16:12:15 2017 +0200 +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp Wed Oct 25 16:13:09 2017 +0200 @@ -272,6 +272,8 @@ bool wait_until_scan_finished(); }; +// This class manages data structures and methods for doing liveness analysis in +// G1's concurrent cycle. class G1ConcurrentMark: public CHeapObj { friend class ConcurrentMarkThread; friend class G1CMRefProcTaskProxy; @@ -285,10 +287,6 @@ ConcurrentMarkThread* _cm_thread; // The thread doing the work G1CollectedHeap* _g1h; // The heap - uint _parallel_marking_threads; // The number of marking - // threads we're using - uint _max_parallel_marking_threads; // Max number of marking - // threads we'll ever use bool _completed_initialization; // Set to true when initialization is complete FreeRegionList _cleanup_list; @@ -312,11 +310,12 @@ // always pointing to the end of the // last claimed region - uint _max_worker_id;// Maximum worker id - uint _active_tasks; // Number of tasks currently active - G1CMTask** _tasks; // Task queue array (max_worker_id length) - G1CMTaskQueueSet* _task_queues; // Task queue set - ParallelTaskTerminator _terminator; // For termination + uint _max_num_tasks; // Maximum number of marking tasks + uint _num_active_tasks; // Number of tasks currently active + G1CMTask** _tasks; // Task queue array (max_worker_id length) + + G1CMTaskQueueSet* _task_queues; // Task queue set + ParallelTaskTerminator _terminator; // For termination // Two sync barriers that are used to synchronize tasks when an // overflow occurs. The algorithm is the following. All tasks enter @@ -363,7 +362,9 @@ double* _accum_task_vtime; // Accumulated task vtime - WorkGang* _parallel_workers; + WorkGang* _concurrent_workers; + uint _num_concurrent_workers; // The number of marking worker threads we're using + uint _max_concurrent_workers; // Maximum number of marking worker threads void weak_refs_work_parallel_part(BoolObjectClosure* is_alive, bool purged_classes); void weak_refs_work(bool clear_all_soft_refs); @@ -398,7 +399,7 @@ HeapWord* finger() { return _finger; } bool concurrent() { return _concurrent; } - uint active_tasks() { return _active_tasks; } + uint active_tasks() { return _num_active_tasks; } ParallelTaskTerminator* terminator() { return &_terminator; } // Claims the next available region to be scanned by a marking @@ -426,7 +427,7 @@ // Returns the task with the given id G1CMTask* task(uint id) { - assert(id < _active_tasks, "Task id %u not within active bounds up to %u", id, _active_tasks); + assert(id < _num_active_tasks, "Task id %u not within active bounds up to %u", id, _num_active_tasks); return _tasks[id]; } @@ -483,7 +484,7 @@ double all_task_accum_vtime() { double ret = 0.0; - for (uint i = 0; i < _max_worker_id; ++i) + for (uint i = 0; i < _max_num_tasks; ++i) ret += _accum_task_vtime[i]; return ret; } @@ -501,13 +502,8 @@ const G1CMBitMap* const prev_mark_bitmap() const { return _prev_mark_bitmap; } G1CMBitMap* next_mark_bitmap() const { return _next_mark_bitmap; } - // Returns the number of GC threads to be used in a concurrent - // phase based on the number of GC threads being used in a STW - // phase. - uint scale_parallel_threads(uint n_par_threads); - - // Calculates the number of GC threads to be used in a concurrent phase. - uint calc_parallel_marking_threads(); + // Calculates the number of concurrent GC threads to be used in the marking phase. + uint calc_active_marking_workers(); // Prepare internal data structures for the next mark cycle. This includes clearing // the next mark bitmap and some internal data structures. This method is intended