diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index 89f2055eeb0..83824c48656 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -123,6 +123,10 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) : _gc_par_phases[MergeLB]->create_thread_work_items("Dirty Cards:", MergeLBDirtyCards); _gc_par_phases[MergeLB]->create_thread_work_items("Skipped Cards:", MergeLBSkippedCards); + _gc_par_phases[CodeRoots]->create_thread_work_items("Scanned Nmethods", CodeRootsScannedNMethods); + + _gc_par_phases[OptCodeRoots]->create_thread_work_items("Scanned Nmethods", CodeRootsScannedNMethods); + _gc_par_phases[MergePSS]->create_thread_work_items("Copied Bytes", MergePSSCopiedBytes); _gc_par_phases[MergePSS]->create_thread_work_items("LAB Waste", MergePSSLABWasteBytes); _gc_par_phases[MergePSS]->create_thread_work_items("LAB Undo Waste", MergePSSLABUndoWasteBytes); diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp index bdad3e66c47..de03ecab99f 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp @@ -134,6 +134,10 @@ class G1GCPhaseTimes : public CHeapObj { MergeLBSkippedCards }; + enum GCCodeRootsWorkItems { + CodeRootsScannedNMethods + }; + enum GCMergePSSWorkItems { MergePSSCopiedBytes, MergePSSLABSize, diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index c899bde6b14..2a7077d3724 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -757,6 +757,25 @@ void G1RemSet::scan_heap_roots(G1ParScanThreadState* pss, p->record_or_add_thread_work_item(scan_phase, worker_id, cl.heap_roots_found(), G1GCPhaseTimes::ScanHRFoundRoots); } +// Wrapper around a CodeBlobClosure to count the number of code blobs scanned. +class G1ScanAndCountCodeBlobClosure : public CodeBlobClosure { + CodeBlobClosure* _cl; + size_t _count; + +public: + G1ScanAndCountCodeBlobClosure(CodeBlobClosure* cl) : _cl(cl), _count(0) { + } + + void do_code_blob(CodeBlob* cb) override { + _cl->do_code_blob(cb); + _count++; + } + + size_t count() const { + return _count; + } +}; + // Heap region closure to be applied to all regions in the current collection set // increment to fix up non-card related roots. class G1ScanCollectionSetRegionClosure : public HeapRegionClosure { @@ -768,6 +787,8 @@ class G1ScanCollectionSetRegionClosure : public HeapRegionClosure { uint _worker_id; + size_t _code_roots_scanned; + size_t _opt_roots_scanned; size_t _opt_refs_scanned; size_t _opt_refs_memory_used; @@ -798,6 +819,7 @@ public: _scan_phase(scan_phase), _code_roots_phase(code_roots_phase), _worker_id(worker_id), + _code_roots_scanned(0), _opt_roots_scanned(0), _opt_refs_scanned(0), _opt_refs_memory_used(0), @@ -822,8 +844,12 @@ public: if (_scan_state->claim_collection_set_region(region_idx)) { EventGCPhaseParallel event; G1EvacPhaseWithTrimTimeTracker timer(_pss, _code_root_scan_time, _code_trim_partially_time); + G1ScanAndCountCodeBlobClosure cl(_pss->closures()->weak_codeblobs()); + // Scan the code root list attached to the current region - r->code_roots_do(_pss->closures()->weak_codeblobs()); + r->code_roots_do(&cl); + + _code_roots_scanned = cl.count(); event.commit(GCId::current(), _worker_id, G1GCPhaseTimes::phase_name(_code_roots_phase)); } @@ -834,6 +860,8 @@ public: Tickspan code_root_scan_time() const { return _code_root_scan_time; } Tickspan code_root_trim_partially_time() const { return _code_trim_partially_time; } + size_t code_roots_scanned() const { return _code_roots_scanned; } + Tickspan rem_set_opt_root_scan_time() const { return _rem_set_opt_root_scan_time; } Tickspan rem_set_opt_trim_partially_time() const { return _rem_set_opt_trim_partially_time; } @@ -856,6 +884,8 @@ void G1RemSet::scan_collection_set_regions(G1ParScanThreadState* pss, p->record_or_add_time_secs(scan_phase, worker_id, cl.rem_set_opt_trim_partially_time().seconds()); p->record_or_add_time_secs(coderoots_phase, worker_id, cl.code_root_scan_time().seconds()); + p->record_or_add_thread_work_item(coderoots_phase, worker_id, cl.code_roots_scanned(), G1GCPhaseTimes::CodeRootsScannedNMethods); + p->add_time_secs(objcopy_phase, worker_id, cl.code_root_trim_partially_time().seconds()); // At this time we record some metrics only for the evacuations after the initial one.