diff -r 4101eab5f3f5 src/hotspot/share/gc/g1/g1CollectedHeap.cpp --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Thu Jul 19 17:22:15 2018 +0200 +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Thu Jul 19 17:23:44 2018 +0200 @@ -3106,7 +3106,6 @@ } bool G1ParEvacuateFollowersClosure::offer_termination() { - G1ParScanThreadState* const pss = par_scan_state(); start_term_time(); const bool res = terminator()->offer_termination(); end_term_time(); @@ -3116,8 +3115,11 @@ void G1ParEvacuateFollowersClosure::do_void() { G1ParScanThreadState* const pss = par_scan_state(); pss->trim_queue(); + // Assume that initially all queues are active. do { - pss->steal_and_trim_queue(queues()); + uint num_live_queues = terminator()->num_live_queues(); + //log_debug(gc)("live queues %u", num_live_queues); + pss->steal_and_trim_queue(queues(), num_live_queues); } while (!offer_termination()); } diff -r 4101eab5f3f5 src/hotspot/share/gc/g1/g1ParScanThreadState.hpp --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp Thu Jul 19 17:22:15 2018 +0200 +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp Thu Jul 19 17:23:44 2018 +0200 @@ -203,7 +203,7 @@ Tickspan trim_ticks() const; void reset_trim_ticks(); - inline void steal_and_trim_queue(RefToScanQueueSet *task_queues); + inline void steal_and_trim_queue(RefToScanQueueSet *task_queues, uint live_queues); // An attempt to evacuate "obj" has failed; take necessary steps. oop handle_evacuation_failure_par(oop obj, markOop m); diff -r 4101eab5f3f5 src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp Thu Jul 19 17:22:15 2018 +0200 +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp Thu Jul 19 17:23:44 2018 +0200 @@ -138,9 +138,9 @@ } } -void G1ParScanThreadState::steal_and_trim_queue(RefToScanQueueSet *task_queues) { +void G1ParScanThreadState::steal_and_trim_queue(RefToScanQueueSet *task_queues, uint num_live_queues) { StarTask stolen_task; - while (task_queues->steal(_worker_id, stolen_task)) { + while (task_queues->steal(_worker_id, num_live_queues, stolen_task)) { assert(verify_task(stolen_task), "sanity"); dispatch_reference(stolen_task); diff -r 4101eab5f3f5 src/hotspot/share/gc/shared/taskqueue.cpp --- a/src/hotspot/share/gc/shared/taskqueue.cpp Thu Jul 19 17:22:15 2018 +0200 +++ b/src/hotspot/share/gc/shared/taskqueue.cpp Thu Jul 19 17:23:44 2018 +0200 @@ -28,6 +28,7 @@ #include "logging/log.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" +#include "runtime/mutex.hpp" #include "runtime/thread.inline.hpp" #include "utilities/debug.hpp" #include "utilities/stack.inline.hpp" @@ -131,8 +132,7 @@ os::sleep(Thread::current(), millis, false); } -bool -ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) { +bool ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) { assert(_n_threads > 0, "Initialization is incorrect"); assert(_offered_termination < _n_threads, "Invariant"); Atomic::inc(&_offered_termination); diff -r 4101eab5f3f5 src/hotspot/share/gc/shared/taskqueue.hpp --- a/src/hotspot/share/gc/shared/taskqueue.hpp Thu Jul 19 17:22:15 2018 +0200 +++ b/src/hotspot/share/gc/shared/taskqueue.hpp Thu Jul 19 17:23:44 2018 +0200 @@ -398,8 +398,12 @@ // Returns if stealing succeeds, and sets "t" to the stolen task. bool steal(uint queue_num, E& t); + // Same as above, but takes an estimation of current number of queues that are currently + // active. This is used to improve the number of attempts made for stealing. + bool steal(uint queue_num, uint num_live_queues, E& t); + bool peek(); - + uint size() const { return _n; } }; @@ -469,7 +473,7 @@ // As above, but it also terminates if the should_exit_termination() // method of the terminator parameter returns true. If terminator is // NULL, then it is ignored. - bool offer_termination(TerminatorTerminator* terminator); + virtual bool offer_termination(TerminatorTerminator* terminator); // Reset the terminator, so that it may be reused again. // The caller is responsible for ensuring that this is done @@ -480,6 +484,8 @@ // given number. void reset_for_reuse(uint n_threads); + // An *estimate* on how many active queues are currently running. + uint num_live_queues() const { return _n_threads - _offered_termination; } #ifdef TRACESPINNING static uint total_yields() { return _total_yields; } static uint total_spins() { return _total_spins; } diff -r 4101eab5f3f5 src/hotspot/share/gc/shared/taskqueue.inline.hpp --- a/src/hotspot/share/gc/shared/taskqueue.inline.hpp Thu Jul 19 17:22:15 2018 +0200 +++ b/src/hotspot/share/gc/shared/taskqueue.inline.hpp Thu Jul 19 17:23:44 2018 +0200 @@ -302,9 +302,14 @@ } } -template bool -GenericTaskQueueSet::steal(uint queue_num, E& t) { - for (uint i = 0; i < 2 * _n; i++) { +template +bool GenericTaskQueueSet::steal(uint queue_num, E& t) { + return steal(queue_num, _n, t); +} + +template +bool GenericTaskQueueSet::steal(uint queue_num, uint num_live_queues, E& t) { + for (uint i = 0; i < 2 * num_live_queues; i++) { TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal_attempt()); if (steal_best_of_2(queue_num, t)) { TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal());