Skip to content

8354555: Add generic JFR events for TaskTerminator #24676

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 33 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c848c3f
Track termination timings and attempts in TaskTerminator
pengxiaolong Apr 15, 2025
022a759
WorkerTask optionally returns TaskTerminator*
pengxiaolong Apr 15, 2025
af63457
Add method to get WorkerDataStats based on data in WorkerDataArray
pengxiaolong Apr 16, 2025
35c0849
Add Jfr event EventGCTaskTerminationStatistics and method TaskTermina…
pengxiaolong Apr 16, 2025
8d3fc3b
Fix typo
pengxiaolong Apr 16, 2025
c57e2a1
Fix build errors, namings
pengxiaolong Apr 16, 2025
cc26471
Invoke emit_termination_statistics after finishing execution
pengxiaolong Apr 16, 2025
32fdd14
Enable new jfr event
pengxiaolong Apr 16, 2025
d3247cb
Not emit event when count is 0
pengxiaolong Apr 16, 2025
6316854
timings should be in ms
pengxiaolong Apr 16, 2025
6b9cbe6
Fix build error
pengxiaolong Apr 16, 2025
313e5c0
Emit EventGCPhaseParallel events to track task terminations
pengxiaolong Apr 22, 2025
6b57aff
Fix wrong string concat
pengxiaolong Apr 22, 2025
ad9d156
Revert changes in WorkerDataArray
pengxiaolong Apr 22, 2025
4cff56f
Remove GCTaskTerminationStatistics event metadata
pengxiaolong Apr 22, 2025
fd25fda
Clean up
pengxiaolong Apr 22, 2025
3fc1207
Remove duplicate EventGCPhaseParallel for termination
pengxiaolong Apr 22, 2025
34f75f4
Address PR comments
pengxiaolong May 8, 2025
e2a9446
Override termination event name for remark
pengxiaolong May 8, 2025
88998d0
termination_event_name must have prefix "Termination"
pengxiaolong May 12, 2025
b3374f5
Fix ident
pengxiaolong May 12, 2025
737f5de
Move TERMINATION_EVENT_NAME_PREFIX_ASSERT to taskTerminator.cpp
pengxiaolong May 12, 2025
59d9da4
Touch up
pengxiaolong May 13, 2025
104ac1b
Add include "workerThread.hpp"
pengxiaolong May 13, 2025
7b1412f
Emit exact same events for G1 as G1 is emitting today from G1Evacuate…
pengxiaolong May 13, 2025
e362b7c
Patch to fix the PR concerns
pengxiaolong May 23, 2025
5ab1c5f
Merge branch 'master' into JDK-8354555
pengxiaolong May 23, 2025
fe67149
Fix jft test failure
pengxiaolong May 23, 2025
17e3255
Merge branch 'openjdk:master' into JDK-8354555
pengxiaolong May 23, 2025
8fb9a40
Merge branch 'openjdk:master' into JDK-8354555
pengxiaolong Jun 3, 2025
c6ff707
Merge branch 'openjdk:master' into JDK-8354555
pengxiaolong Jun 24, 2025
7dd5ebf
Merge branch 'openjdk:master' into JDK-8354555
pengxiaolong Jul 15, 2025
4d60e2e
Merge branch 'openjdk:master' into JDK-8354555
pengxiaolong Jul 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/hotspot/share/gc/g1/g1ConcurrentMark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h,
// _tasks set inside the constructor

_task_queues(new G1CMTaskQueueSet(_max_num_tasks)),
_terminator(_max_num_tasks, _task_queues),
_terminator(_max_num_tasks, _task_queues, TERMINATION_EVENT_NAME("Concurrent Marking")),

_first_overflow_barrier_sync(),
_second_overflow_barrier_sync(),
Expand Down Expand Up @@ -1811,6 +1811,7 @@ class G1RemarkThreadsClosure : public ThreadClosure {

class G1CMRemarkTask : public WorkerTask {
G1ConcurrentMark* _cm;
TaskTerminatorReuseMark _ttmr;
public:
void work(uint worker_id) {
G1CMTask* task = _cm->task(worker_id);
Expand All @@ -1833,9 +1834,8 @@ class G1CMRemarkTask : public WorkerTask {
}

G1CMRemarkTask(G1ConcurrentMark* cm, uint active_workers) :
WorkerTask("Par Remark"), _cm(cm) {
_cm->terminator()->reset_for_reuse(active_workers);
}
WorkerTask("Par Remark"), _cm(cm),
_ttmr(cm->terminator(), active_workers, TERMINATION_EVENT_NAME("Par Remark")) {}
};

void G1ConcurrentMark::finalize_marking() {
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/gc/g1/g1FullGCMarkTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
G1FullGCMarkTask::G1FullGCMarkTask(G1FullCollector* collector) :
G1FullGCTask("G1 Parallel Marking Task", collector),
_root_processor(G1CollectedHeap::heap(), collector->workers()),
_terminator(collector->workers(), collector->array_queue_set()) {
_terminator(collector->workers(), collector->array_queue_set(), TERMINATION_EVENT_NAME("Parallel Marking")) {
}

void G1FullGCMarkTask::work(uint worker_id) {
Expand Down
6 changes: 2 additions & 4 deletions src/hotspot/share/gc/g1/g1YoungCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,12 +553,10 @@ class G1ParEvacuateFollowersClosure : public VoidClosure {
TaskTerminator* terminator() { return _terminator; }

inline bool offer_termination() {
EventGCPhaseParallel event;
G1ParScanThreadState* const pss = par_scan_state();
start_term_time();
const bool res = (terminator() == nullptr) ? true : terminator()->offer_termination();
end_term_time();
event.commit(GCId::current(), pss->worker_id(), G1GCPhaseTimes::phase_name(G1GCPhaseTimes::Termination));
return res;
}

Expand Down Expand Up @@ -667,7 +665,7 @@ class G1EvacuateRegionsBaseTask : public WorkerTask {
_g1h(G1CollectedHeap::heap()),
_per_thread_states(per_thread_states),
_task_queues(task_queues),
_terminator(num_workers, _task_queues),
_terminator(num_workers, _task_queues, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::Termination)),
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

G1EvacuateRegionsBaseTask emits Termination event from G1ParEvacuateFollowersClosure:: offer_termination(), I am trying to keep it same.

_pinned_regions_recorded(false)
{ }

Expand Down Expand Up @@ -940,7 +938,7 @@ class G1STWRefProcProxyTask : public RefProcProxyTask {
: RefProcProxyTask("G1STWRefProcProxyTask", max_workers),
_g1h(g1h),
_pss(pss),
_terminator(max_workers, &task_queues),
_terminator(max_workers, &task_queues, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::Termination)),
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RefProcProxyTask emits Termination event from G1ParEvacuateFollowersClosure:: offer_termination(), I am trying to keep it same as it is today.

_task_queues(task_queues) {}

void work(uint worker_id) override {
Expand Down
6 changes: 3 additions & 3 deletions src/hotspot/share/gc/parallel/psParallelCompact.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1215,7 +1215,7 @@ class MarkFromRootsTask : public WorkerTask {
MarkFromRootsTask(uint active_workers) :
WorkerTask("MarkFromRootsTask"),
_strong_roots_scope(active_workers),
_terminator(active_workers, ParCompactionManager::marking_stacks()),
_terminator(active_workers, ParCompactionManager::marking_stacks(), TERMINATION_EVENT_NAME("Mark")),
_active_workers(active_workers) {}

virtual void work(uint worker_id) {
Expand Down Expand Up @@ -1253,7 +1253,7 @@ class ParallelCompactRefProcProxyTask : public RefProcProxyTask {
public:
ParallelCompactRefProcProxyTask(uint max_workers)
: RefProcProxyTask("ParallelCompactRefProcProxyTask", max_workers),
_terminator(_max_workers, ParCompactionManager::marking_stacks()) {}
_terminator(_max_workers, ParCompactionManager::marking_stacks(), TERMINATION_EVENT_NAME("Reference Processing")) {}

void work(uint worker_id) override {
assert(worker_id < _max_workers, "sanity");
Expand Down Expand Up @@ -1789,7 +1789,7 @@ class FillDensePrefixAndCompactionTask: public WorkerTask {
FillDensePrefixAndCompactionTask(uint active_workers) :
WorkerTask("FillDensePrefixAndCompactionTask"),
_num_workers(active_workers),
_terminator(active_workers, ParCompactionManager::region_task_queues()) {
_terminator(active_workers, ParCompactionManager::region_task_queues(), TERMINATION_EVENT_NAME("Par Compact")) {
}

virtual void work(uint worker_id) {
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/gc/parallel/psScavenge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ class ParallelScavengeRefProcProxyTask : public RefProcProxyTask {
public:
ParallelScavengeRefProcProxyTask(uint max_workers)
: RefProcProxyTask("ParallelScavengeRefProcProxyTask", max_workers),
_terminator(max_workers, ParCompactionManager::marking_stacks()) {}
_terminator(max_workers, ParCompactionManager::marking_stacks(), TERMINATION_EVENT_NAME("Reference Processing")) {}

void work(uint worker_id) override {
assert(worker_id < _max_workers, "sanity");
Expand Down Expand Up @@ -258,7 +258,7 @@ class ScavengeRootsTask : public WorkerTask {
_gen_top(old_gen->object_space()->top()),
_active_workers(active_workers),
_is_old_gen_empty(old_gen->object_space()->is_empty()),
_terminator(active_workers, PSPromotionManager::vm_thread_promotion_manager()->stack_array_depth()) {
_terminator(active_workers, PSPromotionManager::vm_thread_promotion_manager()->stack_array_depth(), TERMINATION_EVENT_NAME("Scavenge")) {
if (!_is_old_gen_empty) {
PSCardTable* card_table = ParallelScavengeHeap::heap()->card_table();
card_table->pre_scavenge(active_workers);
Expand Down
30 changes: 29 additions & 1 deletion src/hotspot/share/gc/shared/taskTerminator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
#include "gc/shared/gc_globals.hpp"
#include "gc/shared/taskqueue.hpp"
#include "gc/shared/taskTerminator.hpp"
#include "jfr/jfrEvents.hpp"
#include "logging/log.hpp"
#include "runtime/globals.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/mutexLocker.hpp"
#include "workerThread.hpp"

TaskTerminator::DelayContext::DelayContext() {
_yield_count = 0;
Expand Down Expand Up @@ -67,9 +69,10 @@ void TaskTerminator::DelayContext::do_step() {
}
}

TaskTerminator::TaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set) :
TaskTerminator::TaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set, const char* termination_event_name) :
_n_threads(n_threads),
_queue_set(queue_set),
_termination_event_name(termination_event_name),
_offered_termination(0),
_blocker(Mutex::nosafepoint, "TaskTerminator_lock"),
_spin_master(nullptr) { }
Expand Down Expand Up @@ -102,6 +105,14 @@ void TaskTerminator::reset_for_reuse(uint n_threads) {
_n_threads = n_threads;
}

const char* TaskTerminator::termination_event_name() {
return _termination_event_name;
}

void TaskTerminator::set_termination_event_name(const char* termination_event_name) {
_termination_event_name = termination_event_name;
}

bool TaskTerminator::exit_termination(size_t tasks, TerminatorTerminator* terminator) {
return tasks > 0 || (terminator != nullptr && terminator->should_exit_termination());
}
Expand All @@ -128,10 +139,27 @@ void TaskTerminator::prepare_for_return(Thread* this_thread, size_t tasks) {
}
}

class TaskTerminationTracker :public StackObj {
TaskTerminator* const _terminator;
uint const _worker_id;
EventGCPhaseParallel _event;
public:
TaskTerminationTracker(TaskTerminator* task_terminator, uint worker_id):
_terminator(task_terminator),
_worker_id(worker_id) { }

~TaskTerminationTracker() {
if (_event.should_commit()) {
_event.commit(GCId::current(), _terminator->threads() > 1 ? _worker_id : 0, _terminator->termination_event_name());
}
}
};

bool TaskTerminator::offer_termination(TerminatorTerminator* terminator) {
assert(_n_threads > 0, "Initialization is incorrect");
assert(_offered_termination < _n_threads, "Invariant");

TaskTerminationTracker termination_tracker(this, WorkerThread::worker_id());
// Single worker, done
if (_n_threads == 1) {
_offered_termination = 1;
Expand Down
34 changes: 33 additions & 1 deletion src/hotspot/share/gc/shared/taskTerminator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ class TaskQueueSetSuper;
class TerminatorTerminator;
class Thread;

#define TERMINATION_EVENT_NAME_PREFIX "Termination"
#define TERMINATION_EVENT_NAME(name) "" TERMINATION_EVENT_NAME_PREFIX ": " name ""

class TaskTerminationTracker;

/*
* Provides a task termination protocol.
*
Expand Down Expand Up @@ -71,6 +76,7 @@ class TaskTerminator : public CHeapObj<mtGC> {

uint _n_threads;
TaskQueueSetSuper* _queue_set;
const char* _termination_event_name;

DEFINE_PAD_MINUS_SIZE(0, DEFAULT_PADDING_SIZE, 0);
volatile uint _offered_termination;
Expand All @@ -94,7 +100,7 @@ class TaskTerminator : public CHeapObj<mtGC> {
NONCOPYABLE(TaskTerminator);

public:
TaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set);
TaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set, const char* termination_event_name = TERMINATION_EVENT_NAME_PREFIX);
~TaskTerminator();

// The current thread has no work, and is ready to terminate if everyone
Expand All @@ -118,6 +124,32 @@ class TaskTerminator : public CHeapObj<mtGC> {
// Same as above but the number of parallel threads is set to the
// given number.
void reset_for_reuse(uint n_threads);

// Get termination event name
const char* termination_event_name();
// Set termination event name
void set_termination_event_name(const char* termination_event_name);

uint threads() {
return _n_threads;
}
};

class TaskTerminatorReuseMark : public StackObj {
private:
TaskTerminator* const _terminator;
const char* _original_event_name;

public:
TaskTerminatorReuseMark(TaskTerminator* terminator, uint active_workers, const char* event_name) :
_terminator(terminator) {
_terminator->reset_for_reuse(active_workers);
_original_event_name = _terminator->termination_event_name();
_terminator->set_termination_event_name(event_name);
};
~TaskTerminatorReuseMark() {
_terminator->set_termination_event_name(_original_event_name);
}
};

#endif // SHARE_GC_SHARED_TASKTERMINATOR_HPP
2 changes: 2 additions & 0 deletions src/hotspot/share/gc/shared/workerThread.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#define SHARE_GC_SHARED_WORKERTHREAD_HPP

#include "gc/shared/gcId.hpp"
#include "gc/shared/taskTerminator.hpp"
#include "memory/allocation.hpp"
#include "runtime/nonJavaThread.hpp"
#include "runtime/semaphore.hpp"
Expand All @@ -35,6 +36,7 @@
class ThreadClosure;
class WorkerTaskDispatcher;
class WorkerThread;
class TaskTerminator;

// An task to be worked on by worker threads
class WorkerTask : public CHeapObj<mtInternal> {
Expand Down
8 changes: 3 additions & 5 deletions src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,28 +221,25 @@ void ShenandoahConcurrentMark::concurrent_mark() {
ShenandoahGenerationType gen_type = _generation->type();
ShenandoahSATBMarkQueueSet& qset = ShenandoahBarrierSet::satb_mark_queue_set();
ShenandoahFlushSATBHandshakeClosure flush_satb(qset);
TaskTerminator terminator(nworkers, task_queues(), TERMINATION_EVENT_NAME("Concurrent Mark"));
for (uint flushes = 0; flushes < ShenandoahMaxSATBBufferFlushes; flushes++) {
switch (gen_type) {
case YOUNG: {
TaskTerminator terminator(nworkers, task_queues());
ShenandoahConcurrentMarkingTask<YOUNG> task(this, &terminator);
workers->run_task(&task);
break;
}
case OLD: {
TaskTerminator terminator(nworkers, task_queues());
ShenandoahConcurrentMarkingTask<OLD> task(this, &terminator);
workers->run_task(&task);
break;
}
case GLOBAL: {
TaskTerminator terminator(nworkers, task_queues());
ShenandoahConcurrentMarkingTask<GLOBAL> task(this, &terminator);
workers->run_task(&task);
break;
}
case NON_GEN: {
TaskTerminator terminator(nworkers, task_queues());
ShenandoahConcurrentMarkingTask<NON_GEN> task(this, &terminator);
workers->run_task(&task);
break;
Expand All @@ -267,6 +264,7 @@ void ShenandoahConcurrentMark::concurrent_mark() {
// No more retries needed, break out.
break;
}
terminator.reset_for_reuse();
}
assert(task_queues()->is_empty() || heap->cancelled_gc(), "Should be empty when not cancelled");
}
Expand Down Expand Up @@ -298,7 +296,7 @@ void ShenandoahConcurrentMark::finish_mark_work() {
task_queues()->reserve(nworkers);

StrongRootsScope scope(nworkers);
TaskTerminator terminator(nworkers, task_queues());
TaskTerminator terminator(nworkers, task_queues(), TERMINATION_EVENT_NAME("Final Mark"));

switch (_generation->type()) {
case YOUNG:{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,10 @@ public static void main(String[] args) throws IOException {
"RebuildFreeList",
"SampleCandidates",
"ResetMarkingState",
"NoteStartOfMark"
"NoteStartOfMark",
"Termination: Parallel Marking",
"Termination: Concurrent Marking",
"Termination: Par Remark"
);

// Some GC phases may or may not occur depending on environment. Filter them out
Expand Down