changeset 60351:dffc5585fa99

8240671: Shenandoah: refactor ShenandoahPhaseTimings Reviewed-by: rkennke, zgu
author shade
date Fri, 06 Mar 2020 17:03:42 +0100
parents 1c40993361d0
children 90c1d2c1f333
files src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp src/hotspot/share/gc/shenandoah/shenandoahStringDedup.cpp src/hotspot/share/gc/shenandoah/shenandoahTimingTracker.cpp src/hotspot/share/gc/shenandoah/shenandoahTimingTracker.hpp src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp
diffstat 11 files changed, 204 insertions(+), 542 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp	Mon Feb 24 19:03:34 2020 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp	Fri Mar 06 17:03:42 2020 +0100
@@ -41,8 +41,8 @@
 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
 #include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
+#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
 #include "gc/shenandoah/shenandoahTaskqueue.inline.hpp"
-#include "gc/shenandoah/shenandoahTimingTracker.hpp"
 #include "gc/shenandoah/shenandoahUtils.hpp"
 
 #include "memory/iterator.inline.hpp"
--- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp	Mon Feb 24 19:03:34 2020 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp	Fri Mar 06 17:03:42 2020 +0100
@@ -41,37 +41,30 @@
 
 #undef GC_PHASE_DECLARE_NAME
 
-ShenandoahPhaseTimings::ShenandoahPhaseTimings() : _policy(NULL) {
+ShenandoahPhaseTimings::ShenandoahPhaseTimings() {
   uint max_workers = MAX2(ConcGCThreads, ParallelGCThreads);
-  _worker_times = new ShenandoahWorkerTimings(max_workers);
+  assert(max_workers > 0, "Must have some GC threads");
+
+#define GC_PAR_PHASE_DECLARE_WORKER_DATA(type, title) \
+  _gc_par_phases[ShenandoahPhaseTimings::type] = new WorkerDataArray<double>(title, max_workers);
+  // Root scanning phases
+  SHENANDOAH_GC_PAR_PHASE_DO(,, GC_PAR_PHASE_DECLARE_WORKER_DATA)
+#undef GC_PAR_PHASE_DECLARE_WORKER_DATA
+
   _policy = ShenandoahHeap::heap()->shenandoah_policy();
   assert(_policy != NULL, "Can not be NULL");
 }
 
-void ShenandoahPhaseTimings::record_phase_start(Phase phase) {
-  _timing_data[phase]._start = os::elapsedTime();
-}
-
-void ShenandoahPhaseTimings::record_phase_end(Phase phase) {
-  assert(_policy != NULL, "Not yet initialized");
-  double end = os::elapsedTime();
-  double elapsed = end - _timing_data[phase]._start;
+void ShenandoahPhaseTimings::record_phase_time(Phase phase, double time) {
   if (!_policy->is_at_shutdown()) {
-    _timing_data[phase]._secs.add(elapsed);
+    _timing_data[phase].add(time);
   }
-  ShenandoahHeap::heap()->heuristics()->record_phase_time(phase, elapsed);
-}
-
-void ShenandoahPhaseTimings::record_phase_time(Phase phase, double time) {
-  assert(_policy != NULL, "Not yet initialized");
-  if (!_policy->is_at_shutdown()) {
-    _timing_data[phase]._secs.add(time);
-  }
+  ShenandoahHeap::heap()->heuristics()->record_phase_time(phase, time);
 }
 
 void ShenandoahPhaseTimings::record_workers_start(Phase phase) {
   for (uint i = 0; i < GCParPhasesSentinel; i++) {
-    _worker_times->reset(i);
+    _gc_par_phases[i]->reset();
   }
 }
 
@@ -97,8 +90,8 @@
   if (phase != _num_phases) {
     // Merge _phase_time to counters below the given phase.
     for (uint i = 0; i < GCParPhasesSentinel; i++) {
-      double t = _worker_times->average(i);
-      _timing_data[phase + i + 1]._secs.add(t);
+      double t = _gc_par_phases[i]->average();
+      _timing_data[phase + i + 1].add(t);
     }
   }
 }
@@ -114,53 +107,38 @@
   out->cr();
 
   for (uint i = 0; i < _num_phases; i++) {
-    if (_timing_data[i]._secs.maximum() != 0) {
-      print_summary_sd(out, _phase_names[i], &(_timing_data[i]._secs));
+    if (_timing_data[i].maximum() != 0) {
+      out->print_cr("%-27s = %8.2lf s (a = %8.0lf us) (n = " INT32_FORMAT_W(5) ") (lvls, us = %8.0lf, %8.0lf, %8.0lf, %8.0lf, %8.0lf)",
+                    _phase_names[i],
+                    _timing_data[i].sum(),
+                    _timing_data[i].avg() * 1000000.0,
+                    _timing_data[i].num(),
+                    _timing_data[i].percentile(0) * 1000000.0,
+                    _timing_data[i].percentile(25) * 1000000.0,
+                    _timing_data[i].percentile(50) * 1000000.0,
+                    _timing_data[i].percentile(75) * 1000000.0,
+                    _timing_data[i].maximum() * 1000000.0
+      );
     }
   }
 }
 
-void ShenandoahPhaseTimings::print_summary_sd(outputStream* out, const char* str, const HdrSeq* seq) const {
-  out->print_cr("%-27s = %8.2lf s (a = %8.0lf us) (n = " INT32_FORMAT_W(5) ") (lvls, us = %8.0lf, %8.0lf, %8.0lf, %8.0lf, %8.0lf)",
-          str,
-          seq->sum(),
-          seq->avg() * 1000000.0,
-          seq->num(),
-          seq->percentile(0)  * 1000000.0,
-          seq->percentile(25) * 1000000.0,
-          seq->percentile(50) * 1000000.0,
-          seq->percentile(75) * 1000000.0,
-          seq->maximum() * 1000000.0
-  );
+void ShenandoahPhaseTimings::record_worker_time(ShenandoahPhaseTimings::GCParPhases phase, uint worker_id, double secs) {
+  _gc_par_phases[phase]->set(worker_id, secs);
 }
 
-ShenandoahWorkerTimings::ShenandoahWorkerTimings(uint max_gc_threads) :
-        _max_gc_threads(max_gc_threads)
-{
-  assert(max_gc_threads > 0, "Must have some GC threads");
-
-#define GC_PAR_PHASE_DECLARE_WORKER_DATA(type, title) \
-  _gc_par_phases[ShenandoahPhaseTimings::type] = new WorkerDataArray<double>(title, max_gc_threads);
-  // Root scanning phases
-  SHENANDOAH_GC_PAR_PHASE_DO(GC_PAR_PHASE_DECLARE_WORKER_DATA)
-#undef GC_PAR_PHASE_DECLARE_WORKER_DATA
+ShenandoahWorkerTimingsTracker::ShenandoahWorkerTimingsTracker(ShenandoahPhaseTimings::GCParPhases phase, uint worker_id) :
+        _phase(phase), _timings(ShenandoahHeap::heap()->phase_timings()), _worker_id(worker_id) {
+  _start_time = os::elapsedTime();
 }
 
-// record the time a phase took in seconds
-void ShenandoahWorkerTimings::record_time_secs(ShenandoahPhaseTimings::GCParPhases phase, uint worker_i, double secs) {
-  _gc_par_phases[phase]->set(worker_i, secs);
+ShenandoahWorkerTimingsTracker::~ShenandoahWorkerTimingsTracker() {
+  _timings->record_worker_time(_phase, _worker_id, os::elapsedTime() - _start_time);
+
+  if (ShenandoahGCPhase::is_root_work_phase()) {
+    ShenandoahPhaseTimings::Phase root_phase = ShenandoahGCPhase::current_phase();
+    ShenandoahPhaseTimings::Phase cur_phase = (ShenandoahPhaseTimings::Phase)((int)root_phase + (int)_phase + 1);
+    _event.commit(GCId::current(), _worker_id, ShenandoahPhaseTimings::phase_name(cur_phase));
+  }
 }
 
-double ShenandoahWorkerTimings::average(uint i) const {
-  return _gc_par_phases[i]->average();
-}
-
-void ShenandoahWorkerTimings::reset(uint i) {
-  _gc_par_phases[i]->reset();
-}
-
-void ShenandoahWorkerTimings::print() const {
-  for (uint i = 0; i < ShenandoahPhaseTimings::GCParPhasesSentinel; i++) {
-    _gc_par_phases[i]->print_summary_on(tty);
-  }
-}
--- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp	Mon Feb 24 19:03:34 2020 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp	Fri Mar 06 17:03:42 2020 +0100
@@ -25,331 +25,147 @@
 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHPHASETIMINGS_HPP
 #define SHARE_GC_SHENANDOAH_SHENANDOAHPHASETIMINGS_HPP
 
+#include "jfr/jfrEvents.hpp"
 #include "gc/shenandoah/shenandoahNumberSeq.hpp"
 #include "gc/shared/workerDataArray.hpp"
 #include "memory/allocation.hpp"
 
 class ShenandoahCollectorPolicy;
-class ShenandoahWorkerTimings;
 class outputStream;
 
-#define SHENANDOAH_GC_PHASE_DO(f)                                                       \
-  f(total_pause_gross,                              "Total Pauses (G)")                 \
-  f(total_pause,                                    "Total Pauses (N)")                 \
-  f(init_mark_gross,                                "Pause Init Mark (G)")              \
-  f(init_mark,                                      "Pause Init Mark (N)")              \
-  f(make_parsable,                                  "  Make Parsable")                  \
-  f(clear_liveness,                                 "  Clear Liveness")                 \
-                                                                                        \
-  /* Per-thread timer block, should have "roots" counters in consistent order */        \
-  f(scan_roots,                                     "  Scan Roots")                     \
-  f(scan_thread_roots,                              "    S: Thread Roots")              \
-  f(scan_code_roots,                                "    S: Code Cache Roots")          \
-  f(scan_universe_roots,                            "    S: Universe Roots")            \
-  f(scan_jni_roots,                                 "    S: JNI Roots")                 \
-  f(scan_jvmti_weak_roots,                          "    S: JVMTI Weak Roots")          \
-  f(scan_jfr_weak_roots,                            "    S: JFR Weak Roots")            \
-  f(scan_jni_weak_roots,                            "    S: JNI Weak Roots")            \
-  f(scan_stringtable_roots,                         "    S: String Table Roots")        \
-  f(scan_resolved_method_table_roots,               "    S: Resolved Table Roots")      \
-  f(scan_vm_global_roots,                           "    S: VM Global Roots")           \
-  f(scan_vm_weak_roots,                             "    S: VM Weak Roots")             \
-  f(scan_synchronizer_roots,                        "    S: Synchronizer Roots")        \
-  f(scan_management_roots,                          "    S: Management Roots")          \
-  f(scan_system_dictionary_roots,                   "    S: System Dict Roots")         \
-  f(scan_cldg_roots,                                "    S: CLDG Roots")                \
-  f(scan_jvmti_roots,                               "    S: JVMTI Roots")               \
-  f(scan_string_dedup_table_roots,                  "    S: Dedup Table Roots")         \
-  f(scan_string_dedup_queue_roots,                  "    S: Dedup Queue Roots")         \
-  f(scan_finish_queues,                             "    S: Finish Queues" )            \
-                                                                                        \
-  f(resize_tlabs,                                   "  Resize TLABs")                   \
-                                                                                        \
-  f(final_mark_gross,                               "Pause Final Mark (G)")             \
-  f(final_mark,                                     "Pause Final Mark (N)")             \
-                                                                                        \
-  /* Per-thread timer block, should have "roots" counters in consistent order */        \
-  f(update_roots,                                   "  Update Roots")                   \
-  f(update_thread_roots,                            "    U: Thread Roots")              \
-  f(update_code_roots,                              "    U: Code Cache Roots")          \
-  f(update_universe_roots,                          "    U: Universe Roots")            \
-  f(update_jni_roots,                               "    U: JNI Roots")                 \
-  f(update_jvmti_weak_roots,                        "    U: JVMTI Weak Roots")          \
-  f(update_jfr_weak_roots,                          "    U: JFR Weak Roots")            \
-  f(update_jni_weak_roots,                          "    U: JNI Weak Roots")            \
-  f(update_stringtable_roots,                       "    U: String Table Roots")        \
-  f(update_resolved_method_table_roots,             "    U: Resolved Table Roots")      \
-  f(update_vm_global_roots,                         "    U: VM Global Roots")           \
-  f(update_vm_weak_roots,                           "    U: VM Weak Roots")             \
-  f(update_synchronizer_roots,                      "    U: Synchronizer Roots")        \
-  f(update_management_roots,                        "    U: Management Roots")          \
-  f(update_system_dictionary_roots,                 "    U: System Dict Roots")         \
-  f(update_cldg_roots,                              "    U: CLDG Roots")                \
-  f(update_jvmti_roots,                             "    U: JVMTI Roots")               \
-  f(update_string_dedup_table_roots,                "    U: Dedup Table Roots")         \
-  f(update_string_dedup_queue_roots,                "    U: Dedup Queue Roots")         \
-  f(update_finish_queues,                           "    U: Finish Queues")             \
-                                                                                        \
-  f(finish_queues,                                  "  Finish Queues")                  \
-  f(weakrefs,                                       "  Weak References")                \
-  f(weakrefs_process,                               "    Process")                      \
-  f(purge,                                          "  System Purge")                   \
-  f(purge_class_unload,                             "    Unload Classes")               \
-  f(purge_par,                                      "    Parallel Cleanup")             \
-  f(purge_cldg,                                     "    CLDG")                         \
-  f(complete_liveness,                              "  Complete Liveness")              \
-  f(retire_tlabs,                                   "  Retire TLABs")                   \
-  f(sync_pinned,                                    "  Sync Pinned")                    \
-  f(trash_cset,                                     "  Trash CSet")                     \
-  f(prepare_evac,                                   "  Prepare Evacuation")             \
-                                                                                        \
-  /* Per-thread timer block, should have "roots" counters in consistent order */        \
-  f(init_evac,                                      "  Initial Evacuation")             \
-  f(evac_thread_roots,                              "    E: Thread Roots")              \
-  f(evac_code_roots,                                "    E: Code Cache Roots")          \
-  f(evac_universe_roots,                            "    E: Universe Roots")            \
-  f(evac_jni_roots,                                 "    E: JNI Roots")                 \
-  f(evac_jvmti_weak_roots,                          "    E: JVMTI Weak Roots")          \
-  f(evac_jfr_weak_roots,                            "    E: JFR Weak Roots")            \
-  f(evac_jni_weak_roots,                            "    E: JNI Weak Roots")            \
-  f(evac_stringtable_roots,                         "    E: String Table Roots")        \
-  f(evac_resolved_method_table_roots,               "    E: Resolved Table Roots")      \
-  f(evac_vm_global_roots,                           "    E: VM Global Roots")           \
-  f(evac_vm_weak_roots,                             "    E: VM Weak Roots")             \
-  f(evac_synchronizer_roots,                        "    E: Synchronizer Roots")        \
-  f(evac_management_roots,                          "    E: Management Roots")          \
-  f(evac_system_dictionary_roots,                   "    E: System Dict Roots")         \
-  f(evac_cldg_roots,                                "    E: CLDG Roots")                \
-  f(evac_jvmti_roots,                               "    E: JVMTI Roots")               \
-  f(evac_string_dedup_table_roots,                  "    E: String Dedup Table Roots")  \
-  f(evac_string_dedup_queue_roots,                  "    E: String Dedup Queue Roots")  \
-  f(evac_finish_queues,                             "    E: Finish Queues")             \
-                                                                                        \
-  f(final_evac_gross,                               "Pause Final Evac (G)")             \
-  f(final_evac,                                     "Pause Final Evac (N)")             \
-  f(final_evac_retire_gclabs,                       "  Retire GCLABs")                  \
-                                                                                        \
-  f(init_update_refs_gross,                         "Pause Init  Update Refs (G)")      \
-  f(init_update_refs,                               "Pause Init  Update Refs (N)")      \
-  f(init_update_refs_retire_gclabs,                 "  Retire GCLABs")                  \
-  f(init_update_refs_prepare,                       "  Prepare")                        \
-                                                                                        \
-  f(final_update_refs_gross,                         "Pause Final Update Refs (G)")     \
-  f(final_update_refs,                               "Pause Final Update Refs (N)")     \
-  f(final_update_refs_finish_work,                   "  Finish Work")                   \
-                                                                                        \
-  /* Per-thread timer block, should have "roots" counters in consistent order */        \
-  f(final_update_refs_roots,                         "  Update Roots")                  \
-  f(final_update_refs_thread_roots,                  "    UR: Thread Roots")            \
-  f(final_update_refs_code_roots,                    "    UR: Code Cache Roots")        \
-  f(final_update_refs_universe_roots,                "    UR: Universe Roots")          \
-  f(final_update_refs_jni_roots,                     "    UR: JNI Roots")               \
-  f(final_update_jvmti_weak_roots,                   "    UR: JVMTI Weak Roots")        \
-  f(final_update_jfr_weak_roots,                     "    UR: JFR Weak Roots")          \
-  f(final_update_jni_weak_roots,                     "    UR: JNI Weak Roots")          \
-  f(final_update_stringtable_roots,                  "    UR: String Table Roots")      \
-  f(final_update_resolved_method_table_roots,        "    UR: Resolved Table Roots")    \
-  f(final_update_vm_global_roots,                    "    UR: VM Global Roots")         \
-  f(final_update_vm_weak_roots,                      "    UR: VM Weak Roots")           \
-  f(final_update_refs_synchronizer_roots,            "    UR: Synchronizer Roots")      \
-  f(final_update_refs_management_roots,              "    UR: Management Roots")        \
-  f(final_update_refs_system_dict_roots,             "    UR: System Dict Roots")       \
-  f(final_update_refs_cldg_roots,                    "    UR: CLDG Roots")              \
-  f(final_update_refs_jvmti_roots,                   "    UR: JVMTI Roots")             \
-  f(final_update_refs_string_dedup_table_roots,      "    UR: Dedup Table Roots")       \
-  f(final_update_refs_string_dedup_queue_roots,      "    UR: Dedup Queue Roots")       \
-  f(final_update_refs_finish_queues,                 "    UR: Finish Queues")           \
-                                                                                        \
-  f(final_update_refs_sync_pinned,                   "  Sync Pinned")                   \
-  f(final_update_refs_trash_cset,                    "  Trash CSet")                    \
-                                                                                        \
-  f(degen_gc_gross,                                  "Pause Degenerated GC (G)")        \
-  f(degen_gc,                                        "Pause Degenerated GC (N)")        \
-                                                                                        \
-  /* Per-thread timer block, should have "roots" counters in consistent order */        \
-  f(degen_gc_update_roots,                           "  Degen Update Roots")            \
-  f(degen_gc_update_thread_roots,                    "    DU: Thread Roots")            \
-  f(degen_gc_update_code_roots,                      "    DU: Code Cache Roots")        \
-  f(degen_gc_update_universe_roots,                  "    DU: Universe Roots")          \
-  f(degen_gc_update_jni_roots,                       "    DU: JNI Roots")               \
-  f(degen_gc_update_jvmti_weak_roots,                "    DU: JVMTI Weak Roots")        \
-  f(degen_gc_update_jfr_weak_roots,                  "    DU: JFR Weak Roots")          \
-  f(degen_gc_update_jni_weak_roots,                  "    DU: JNI Weak Roots")          \
-  f(degen_gc_update_stringtable_roots,               "    DU: String Table Roots")      \
-  f(degen_gc_update_resolved_method_table_roots,     "    DU: Resolved Table Roots")    \
-  f(degen_gc_update_vm_global_roots,                 "    DU: VM Global Roots")         \
-  f(degen_gc_update_vm_weak_roots,                   "    DU: VM Weak Roots")           \
-  f(degen_gc_update_synchronizer_roots,              "    DU: Synchronizer Roots")      \
-  f(degen_gc_update_management_roots,                "    DU: Management Roots")        \
-  f(degen_gc_update_system_dict_roots,               "    DU: System Dict Roots")       \
-  f(degen_gc_update_cldg_roots,                      "    DU: CLDG Roots")              \
-  f(degen_gc_update_jvmti_roots,                     "    DU: JVMTI Roots")             \
-  f(degen_gc_update_string_dedup_table_roots,        "    DU: Dedup Table Roots")       \
-  f(degen_gc_update_string_dedup_queue_roots,        "    DU: Dedup Queue Roots")       \
-  f(degen_gc_update_finish_queues,                   "    DU: Finish Queues")           \
-                                                                                        \
-  f(init_traversal_gc_gross,                         "Pause Init Traversal (G)")        \
-  f(init_traversal_gc,                               "Pause Init Traversal (N)")        \
-  f(traversal_gc_prepare,                            "  Prepare")                       \
-  f(traversal_gc_make_parsable,                      "    Make Parsable")               \
-  f(traversal_gc_resize_tlabs,                       "    Resize TLABs")                \
-  f(traversal_gc_prepare_sync_pinned,                "    Sync Pinned")                 \
-                                                                                        \
-  /* Per-thread timer block, should have "roots" counters in consistent order */        \
-  f(init_traversal_gc_work,                          "  Work")                          \
-  f(init_traversal_gc_thread_roots,                  "    TI: Thread Roots")            \
-  f(init_traversal_gc_code_roots,                    "    TI: Code Cache Roots")        \
-  f(init_traversal_gc_universe_roots,                "    TI: Universe Roots")          \
-  f(init_traversal_gc_jni_roots,                     "    TI: JNI Roots")               \
-  f(init_traversal_gc_jvmti_weak_roots,              "    TI: JVMTI Weak Roots")        \
-  f(init_traversal_gc_jfr_weak_roots,                "    TI: JFR Weak Roots")          \
-  f(init_traversal_gc_jni_weak_roots,                "    TI: JNI Weak Roots")          \
-  f(init_traversal_gc_stringtable_roots,             "    TI: String Table Roots")      \
-  f(init_traversal_gc_resolved_method_table_roots,   "    TI: Resolved Table Roots")    \
-  f(init_traversal_gc_vm_global_roots,               "    TI: VM Global Roots")         \
-  f(init_traversal_gc_vm_weak_roots,                 "    TI: VM Weak Roots")           \
-  f(init_traversal_gc_synchronizer_roots,            "    TI: Synchronizer Roots")      \
-  f(init_traversal_gc_management_roots,              "    TI: Management Roots")        \
-  f(init_traversal_gc_system_dict_roots,             "    TI: System Dict Roots")       \
-  f(init_traversal_gc_cldg_roots,                    "    TI: CLDG Roots")              \
-  f(init_traversal_gc_jvmti_roots,                   "    TI: JVMTI Roots")             \
-  f(init_traversal_gc_string_dedup_table_roots,      "    TI: Dedup Table Roots")       \
-  f(init_traversal_gc_string_dedup_queue_roots,      "    TI: Dedup Queue Roots")       \
-  f(init_traversal_gc_finish_queues,                 "    TI: Finish Queues")           \
-                                                                                        \
-  f(final_traversal_gc_gross,                        "Pause Final Traversal (G)")       \
-  f(final_traversal_gc,                              "Pause Final Traversal (N)")       \
-                                                                                        \
-  /* Per-thread timer block, should have "roots" counters in consistent order */        \
-  f(final_traversal_gc_work,                         "  Work")                          \
-  f(final_traversal_gc_thread_roots,                 "    TF: Thread Roots")            \
-  f(final_traversal_gc_code_roots,                   "    TF: Code Cache Roots")        \
-  f(final_traversal_gc_universe_roots,               "    TF: Universe Roots")          \
-  f(final_traversal_gc_jni_roots,                    "    TF: JNI Roots")               \
-  f(final_traversal_gc_jvmti_weak_roots,             "    TF: JVMTI Weak Roots")        \
-  f(final_traversal_gc_jfr_weak_roots,               "    TF: JFR Weak Roots")          \
-  f(final_traversal_gc_jni_weak_roots,               "    TF: JNI Weak Roots")          \
-  f(final_traversal_gc_stringtable_roots,            "    TF: String Table Roots")      \
-  f(final_traversal_gc_resolved_method_table_roots,  "    TF: Resolved Table Roots")    \
-  f(final_traversal_gc_vm_global_roots,              "    TF: VM Global Roots")         \
-  f(final_traversal_gc_vm_weak_roots,                "    TF: VM Weak Roots")           \
-  f(final_traversal_gc_synchronizer_roots,           "    TF: Synchronizer Roots")      \
-  f(final_traversal_gc_management_roots,             "    TF: Management Roots")        \
-  f(final_traversal_gc_system_dict_roots,            "    TF: System Dict Roots")       \
-  f(final_traversal_gc_cldg_roots,                   "    TF: CLDG Roots")              \
-  f(final_traversal_gc_jvmti_roots,                  "    TF: JVMTI Roots")             \
-  f(final_traversal_gc_string_dedup_table_roots,     "    TF: Dedup Table Roots")       \
-  f(final_traversal_gc_string_dedup_queue_roots,     "    TF: Dedup Queue Roots")       \
-  f(final_traversal_gc_finish_queues,                "    TF: Finish Queues")           \
-                                                                                        \
-  /* Per-thread timer block, should have "roots" counters in consistent order */        \
-  f(final_traversal_update_roots,                       "  Update Roots")               \
-  f(final_traversal_update_thread_roots,                "    TU: Thread Roots")         \
-  f(final_traversal_update_code_roots,                  "    TU: Code Cache Roots")     \
-  f(final_traversal_update_universe_roots,              "    TU: Universe Roots")       \
-  f(final_traversal_update_jni_roots,                   "    TU: JNI Roots")            \
-  f(final_traversal_update_jvmti_weak_roots,            "    TU: JVMTI Weak Roots")     \
-  f(final_traversal_update_jfr_weak_roots,              "    TU: JFR Weak Roots")       \
-  f(final_traversal_update_jni_weak_roots,              "    TU: JNI Weak Roots")       \
-  f(final_traversal_update_stringtable_roots,           "    TU: String Table Roots")   \
-  f(final_traversal_update_resolved_method_table_roots, "    TU: Resolved Table Roots") \
-  f(final_traversal_update_vm_global_roots,             "    TU: VM Global Roots")      \
-  f(final_traversal_update_vm_weak_roots,               "    TU: VM Weak Roots")        \
-  f(final_traversal_update_synchronizer_roots,          "    TU: Synchronizer Roots")   \
-  f(final_traversal_update_management_roots,            "    TU: Management Roots")     \
-  f(final_traversal_update_system_dict_roots,           "    TU: System Dict Roots")    \
-  f(final_traversal_update_cldg_roots,                  "    TU: CLDG Roots")           \
-  f(final_traversal_update_jvmti_roots,                 "    TU: JVMTI Roots")          \
-  f(final_traversal_update_string_dedup_table_roots,    "    TU: Dedup Table Roots")    \
-  f(final_traversal_update_string_dedup_queue_roots,    "    TU: Dedup Queue Roots")    \
-  f(final_traversal_update_finish_queues,               "    TU: Finish Queues")        \
-                                                                                        \
-  f(traversal_gc_sync_pinned,                        "  Sync Pinned")                   \
-  f(traversal_gc_cleanup,                            "  Cleanup")                       \
-                                                                                        \
-  f(full_gc_gross,                                   "Pause Full GC (G)")               \
-  f(full_gc,                                         "Pause Full GC (N)")               \
-  f(full_gc_heapdumps,                               "  Heap Dumps")                    \
-  f(full_gc_prepare,                                 "  Prepare")                       \
-                                                                                        \
-  /* Per-thread timer block, should have "roots" counters in consistent order */        \
-  f(full_gc_roots,                                   "  Roots")                         \
-  f(full_gc_thread_roots,                            "    F: Thread Roots")             \
-  f(full_gc_code_roots,                              "    F: Code Cache Roots")         \
-  f(full_gc_universe_roots,                          "    F: Universe Roots")           \
-  f(full_gc_jni_roots,                               "    F: JNI Roots")                \
-  f(full_gc_jvmti_weak_roots,                        "    F: JVMTI Weak Roots")         \
-  f(full_gc_jfr_weak_roots,                          "    F: JFR Weak Roots")           \
-  f(full_gc_jni_weak_roots,                          "    F: JNI Weak Roots")           \
-  f(full_gc_stringtable_roots,                       "    F: String Table Roots")       \
-  f(full_gc_resolved_method_table_roots,             "    F: Resolved Table Roots")     \
-  f(full_gc_vm_global_roots,                         "    F: VM Global Roots")          \
-  f(full_gc_vm_weak_roots,                           "    F: VM Weak Roots")            \
-  f(full_gc_synchronizer_roots,                      "    F: Synchronizer Roots")       \
-  f(full_gc_management_roots,                        "    F: Management Roots")         \
-  f(full_gc_system_dictionary_roots,                 "    F: System Dict Roots")        \
-  f(full_gc_cldg_roots,                              "    F: CLDG Roots")               \
-  f(full_gc_jvmti_roots,                             "    F: JVMTI Roots")              \
-  f(full_gc_string_dedup_table_roots,                "    F: Dedup Table Roots")        \
-  f(full_gc_string_dedup_queue_roots,                "    F: Dedup Queue Roots")        \
-  f(full_gc_finish_queues,                           "    F: Finish Queues")            \
-                                                                                        \
-  f(full_gc_mark,                                    "  Mark")                          \
-  f(full_gc_mark_finish_queues,                      "    Finish Queues")               \
-  f(full_gc_weakrefs,                                "    Weak References")             \
-  f(full_gc_weakrefs_process,                        "      Process")                   \
-  f(full_gc_purge,                                   "    System Purge")                \
-  f(full_gc_purge_class_unload,                      "      Unload Classes")            \
-  f(full_gc_purge_par,                               "    Parallel Cleanup")            \
-  f(full_gc_purge_cldg,                              "    CLDG")                        \
-  f(full_gc_calculate_addresses,                     "  Calculate Addresses")           \
-  f(full_gc_calculate_addresses_regular,             "    Regular Objects")             \
-  f(full_gc_calculate_addresses_humong,              "    Humongous Objects")           \
-  f(full_gc_adjust_pointers,                         "  Adjust Pointers")               \
-  f(full_gc_copy_objects,                            "  Copy Objects")                  \
-  f(full_gc_copy_objects_regular,                    "    Regular Objects")             \
-  f(full_gc_copy_objects_humong,                     "    Humongous Objects")           \
-  f(full_gc_copy_objects_reset_complete,             "    Reset Complete Bitmap")       \
-  f(full_gc_copy_objects_rebuild,                    "    Rebuild Region Sets")         \
-  f(full_gc_resize_tlabs,                            "  Resize TLABs")                  \
-                                                                                        \
-  /* Longer concurrent phases at the end */                                             \
-  f(conc_reset,                                      "Concurrent Reset")                \
-  f(conc_mark,                                       "Concurrent Marking")              \
-  f(conc_preclean,                                   "Concurrent Precleaning")          \
-  f(conc_roots,                                      "Concurrent Roots")                \
-  f(conc_evac,                                       "Concurrent Evacuation")           \
-  f(conc_update_refs,                                "Concurrent Update Refs")          \
-  f(conc_cleanup,                                    "Concurrent Cleanup")              \
-  f(conc_traversal,                                  "Concurrent Traversal")            \
-                                                                                        \
-  f(conc_uncommit,                                   "Concurrent Uncommit")             \
-                                                                                        \
-  /* Unclassified */                                                                    \
-  f(pause_other,                                     "Pause Other")                     \
-  f(conc_other,                                      "Concurrent Other")                \
+#define SHENANDOAH_GC_PAR_PHASE_DO(CNT_PREFIX, DESC_PREFIX, f)                         \
+  f(CNT_PREFIX ## ThreadRoots,              DESC_PREFIX "Thread Roots")                \
+  f(CNT_PREFIX ## CodeCacheRoots,           DESC_PREFIX "Code Cache Roots")            \
+  f(CNT_PREFIX ## UniverseRoots,            DESC_PREFIX "Universe Roots")              \
+  f(CNT_PREFIX ## JNIRoots,                 DESC_PREFIX "JNI Handles Roots")           \
+  f(CNT_PREFIX ## JVMTIWeakRoots,           DESC_PREFIX "JVMTI Weak Roots")            \
+  f(CNT_PREFIX ## JFRWeakRoots,             DESC_PREFIX "JFR Weak Roots")              \
+  f(CNT_PREFIX ## JNIWeakRoots,             DESC_PREFIX "JNI Weak Roots")              \
+  f(CNT_PREFIX ## StringTableRoots,         DESC_PREFIX "String Table Roots")          \
+  f(CNT_PREFIX ## ResolvedMethodTableRoots, DESC_PREFIX "Resolved Table Roots")        \
+  f(CNT_PREFIX ## VMGlobalRoots,            DESC_PREFIX "VM Global Roots")             \
+  f(CNT_PREFIX ## VMWeakRoots,              DESC_PREFIX "VM Weak Roots")               \
+  f(CNT_PREFIX ## ObjectSynchronizerRoots,  DESC_PREFIX "Synchronizer Roots")          \
+  f(CNT_PREFIX ## ManagementRoots,          DESC_PREFIX "Management Roots")            \
+  f(CNT_PREFIX ## SystemDictionaryRoots,    DESC_PREFIX "System Dict Roots")           \
+  f(CNT_PREFIX ## CLDGRoots,                DESC_PREFIX "CLDG Roots")                  \
+  f(CNT_PREFIX ## JVMTIRoots,               DESC_PREFIX "JVMTI Roots")                 \
+  f(CNT_PREFIX ## StringDedupTableRoots,    DESC_PREFIX "Dedup Table Roots")           \
+  f(CNT_PREFIX ## StringDedupQueueRoots,    DESC_PREFIX "Dedup Queue Roots")           \
+  f(CNT_PREFIX ## FinishQueues,             DESC_PREFIX "Finish Queues")               \
   // end
 
-#define SHENANDOAH_GC_PAR_PHASE_DO(f)                           \
-  f(ThreadRoots,              "Thread Roots (ms):")              \
-  f(CodeCacheRoots,           "CodeCache Roots (ms):")           \
-  f(UniverseRoots,            "Universe Roots (ms):")            \
-  f(JNIRoots,                 "JNI Handles Roots (ms):")         \
-  f(JVMTIWeakRoots,           "JVMTI Weak Roots (ms):")          \
-  f(JFRWeakRoots,             "JFR Weak Roots (ms):")            \
-  f(JNIWeakRoots,             "JNI Weak Roots (ms):")            \
-  f(StringTableRoots,         "StringTable Roots(ms):")          \
-  f(ResolvedMethodTableRoots, "Resolved Table Roots(ms):")       \
-  f(VMGlobalRoots,            "VM Global Roots(ms)")             \
-  f(VMWeakRoots,              "VM Weak Roots(ms)")               \
-  f(ObjectSynchronizerRoots,  "ObjectSynchronizer Roots (ms):")  \
-  f(ManagementRoots,          "Management Roots (ms):")          \
-  f(SystemDictionaryRoots,    "SystemDictionary Roots (ms):")    \
-  f(CLDGRoots,                "CLDG Roots (ms):")                \
-  f(JVMTIRoots,               "JVMTI Roots (ms):")               \
-  f(StringDedupTableRoots,    "String Dedup Table Roots (ms):")  \
-  f(StringDedupQueueRoots,    "String Dedup Queue Roots (ms):")  \
-  f(FinishQueues,             "Finish Queues (ms):")             \
+#define SHENANDOAH_GC_PHASE_DO(f)                                                      \
+  f(total_pause_gross,                              "Total Pauses (G)")                \
+  f(total_pause,                                    "Total Pauses (N)")                \
+                                                                                       \
+  f(init_mark_gross,                                "Pause Init Mark (G)")             \
+  f(init_mark,                                      "Pause Init Mark (N)")             \
+  f(make_parsable,                                  "  Make Parsable")                 \
+  f(clear_liveness,                                 "  Clear Liveness")                \
+  f(scan_roots,                                     "  Scan Roots")                    \
+  SHENANDOAH_GC_PAR_PHASE_DO(scan_,                 "    S: ", f)                      \
+  f(resize_tlabs,                                   "  Resize TLABs")                  \
+                                                                                       \
+  f(final_mark_gross,                               "Pause Final Mark (G)")            \
+  f(final_mark,                                     "Pause Final Mark (N)")            \
+  f(update_roots,                                   "  Update Roots")                  \
+  SHENANDOAH_GC_PAR_PHASE_DO(update_,               "    U: ", f)                      \
+  f(finish_queues,                                  "  Finish Queues")                 \
+  f(weakrefs,                                       "  Weak References")               \
+  f(weakrefs_process,                               "    Process")                     \
+  f(purge,                                          "  System Purge")                  \
+  f(purge_class_unload,                             "    Unload Classes")              \
+  f(purge_par,                                      "    Parallel Cleanup")            \
+  f(purge_cldg,                                     "    CLDG")                        \
+  f(complete_liveness,                              "  Complete Liveness")             \
+  f(retire_tlabs,                                   "  Retire TLABs")                  \
+  f(sync_pinned,                                    "  Sync Pinned")                   \
+  f(trash_cset,                                     "  Trash CSet")                    \
+  f(prepare_evac,                                   "  Prepare Evacuation")            \
+  f(init_evac,                                      "  Initial Evacuation")            \
+  SHENANDOAH_GC_PAR_PHASE_DO(evac_,                 "    E: ", f)                      \
+                                                                                       \
+  f(final_evac_gross,                               "Pause Final Evac (G)")            \
+  f(final_evac,                                     "Pause Final Evac (N)")            \
+  f(final_evac_retire_gclabs,                       "  Retire GCLABs")                 \
+                                                                                       \
+  f(init_update_refs_gross,                         "Pause Init  Update Refs (G)")     \
+  f(init_update_refs,                               "Pause Init  Update Refs (N)")     \
+  f(init_update_refs_retire_gclabs,                 "  Retire GCLABs")                 \
+  f(init_update_refs_prepare,                       "  Prepare")                       \
+                                                                                       \
+  f(final_update_refs_gross,                        "Pause Final Update Refs (G)")     \
+  f(final_update_refs,                              "Pause Final Update Refs (N)")     \
+  f(final_update_refs_finish_work,                  "  Finish Work")                   \
+  f(final_update_refs_roots,                        "  Update Roots")                  \
+  SHENANDOAH_GC_PAR_PHASE_DO(final_update_,         "    UR: ", f)                     \
+  f(final_update_refs_sync_pinned,                  "  Sync Pinned")                   \
+  f(final_update_refs_trash_cset,                   "  Trash CSet")                    \
+                                                                                       \
+  f(degen_gc_gross,                                 "Pause Degenerated GC (G)")        \
+  f(degen_gc,                                       "Pause Degenerated GC (N)")        \
+  f(degen_gc_update_roots,                          "  Degen Update Roots")            \
+  SHENANDOAH_GC_PAR_PHASE_DO(degen_gc_update_,      "    DU: ", f)                     \
+                                                                                       \
+  f(init_traversal_gc_gross,                        "Pause Init Traversal (G)")        \
+  f(init_traversal_gc,                              "Pause Init Traversal (N)")        \
+  f(traversal_gc_prepare,                           "  Prepare")                       \
+  f(traversal_gc_make_parsable,                     "    Make Parsable")               \
+  f(traversal_gc_resize_tlabs,                      "    Resize TLABs")                \
+  f(traversal_gc_prepare_sync_pinned,               "    Sync Pinned")                 \
+  f(init_traversal_gc_work,                         "  Work")                          \
+  SHENANDOAH_GC_PAR_PHASE_DO(init_traversal_,       "    TI: ", f)                     \
+                                                                                       \
+  f(final_traversal_gc_gross,                       "Pause Final Traversal (G)")       \
+  f(final_traversal_gc,                             "Pause Final Traversal (N)")       \
+  f(final_traversal_gc_work,                        "  Work")                          \
+  SHENANDOAH_GC_PAR_PHASE_DO(final_trav_gc_,        "    TF: ", f)                     \
+  f(final_traversal_update_roots,                   "  Update Roots")                  \
+  SHENANDOAH_GC_PAR_PHASE_DO(final_trav_update_,    "    TU: ", f)                     \
+  f(traversal_gc_sync_pinned,                       "  Sync Pinned")                   \
+  f(traversal_gc_cleanup,                           "  Cleanup")                       \
+                                                                                       \
+  f(full_gc_gross,                                  "Pause Full GC (G)")               \
+  f(full_gc,                                        "Pause Full GC (N)")               \
+  f(full_gc_heapdumps,                              "  Heap Dumps")                    \
+  f(full_gc_prepare,                                "  Prepare")                       \
+  f(full_gc_roots,                                  "  Roots")                         \
+  SHENANDOAH_GC_PAR_PHASE_DO(full_gc_,              "    F: ", f)                      \
+  f(full_gc_mark,                                   "  Mark")                          \
+  f(full_gc_mark_finish_queues,                     "    Finish Queues")               \
+  f(full_gc_weakrefs,                               "    Weak References")             \
+  f(full_gc_weakrefs_process,                       "      Process")                   \
+  f(full_gc_purge,                                  "    System Purge")                \
+  f(full_gc_purge_class_unload,                     "      Unload Classes")            \
+  f(full_gc_purge_par,                              "    Parallel Cleanup")            \
+  f(full_gc_purge_cldg,                             "    CLDG")                        \
+  f(full_gc_calculate_addresses,                    "  Calculate Addresses")           \
+  f(full_gc_calculate_addresses_regular,            "    Regular Objects")             \
+  f(full_gc_calculate_addresses_humong,             "    Humongous Objects")           \
+  f(full_gc_adjust_pointers,                        "  Adjust Pointers")               \
+  f(full_gc_copy_objects,                           "  Copy Objects")                  \
+  f(full_gc_copy_objects_regular,                   "    Regular Objects")             \
+  f(full_gc_copy_objects_humong,                    "    Humongous Objects")           \
+  f(full_gc_copy_objects_reset_complete,            "    Reset Complete Bitmap")       \
+  f(full_gc_copy_objects_rebuild,                   "    Rebuild Region Sets")         \
+  f(full_gc_resize_tlabs,                           "  Resize TLABs")                  \
+                                                                                       \
+  /* Longer concurrent phases at the end */                                            \
+  f(conc_reset,                                     "Concurrent Reset")                \
+  f(conc_mark,                                      "Concurrent Marking")              \
+  f(conc_preclean,                                  "Concurrent Precleaning")          \
+  f(conc_roots,                                     "Concurrent Roots")                \
+  f(conc_evac,                                      "Concurrent Evacuation")           \
+  f(conc_update_refs,                               "Concurrent Update Refs")          \
+  f(conc_cleanup,                                   "Concurrent Cleanup")              \
+  f(conc_traversal,                                 "Concurrent Traversal")            \
+                                                                                       \
+  f(conc_uncommit,                                  "Concurrent Uncommit")             \
+                                                                                       \
+  /* Unclassified */                                                                   \
+  f(pause_other,                                    "Pause Other")                     \
+  f(conc_other,                                     "Concurrent Other")                \
   // end
 
 class ShenandoahPhaseTimings : public CHeapObj<mtGC> {
@@ -361,41 +177,25 @@
     _num_phases
   };
 
-  // These are the subphases of GC phases (scan_roots, update_roots,
-  // init_evac, final_update_refs_roots and full_gc_roots).
-  // Make sure they are following this order.
   enum GCParPhases {
-    SHENANDOAH_GC_PAR_PHASE_DO(GC_PHASE_DECLARE_ENUM)
+    SHENANDOAH_GC_PAR_PHASE_DO(,, GC_PHASE_DECLARE_ENUM)
     GCParPhasesSentinel
   };
 
 #undef GC_PHASE_DECLARE_ENUM
 
 private:
-  struct TimingData {
-    HdrSeq _secs;
-    double _start;
-  };
-
-private:
-  TimingData          _timing_data[_num_phases];
+  HdrSeq              _timing_data[_num_phases];
   static const char*  _phase_names[_num_phases];
 
-  ShenandoahWorkerTimings*      _worker_times;
-
+  WorkerDataArray<double>*   _gc_par_phases[ShenandoahPhaseTimings::GCParPhasesSentinel];
   ShenandoahCollectorPolicy* _policy;
 
 public:
   ShenandoahPhaseTimings();
 
-  ShenandoahWorkerTimings* const worker_times() const { return _worker_times; }
-
-  // record phase start
-  void record_phase_start(Phase phase);
-  // record phase end and return elapsed time in seconds for the phase
-  void record_phase_end(Phase phase);
-  // record an elapsed time for the phase
   void record_phase_time(Phase phase, double time);
+  void record_worker_time(GCParPhases phase, uint worker_id, double time);
 
   void record_workers_start(Phase phase);
   void record_workers_end(Phase phase);
@@ -406,26 +206,19 @@
   }
 
   void print_on(outputStream* out) const;
-
-private:
-  void init_phase_names();
-  void print_summary_sd(outputStream* out, const char* str, const HdrSeq* seq) const;
 };
 
-class ShenandoahWorkerTimings : public CHeapObj<mtGC> {
+class ShenandoahWorkerTimingsTracker : public StackObj {
 private:
-  uint _max_gc_threads;
-  WorkerDataArray<double>* _gc_par_phases[ShenandoahPhaseTimings::GCParPhasesSentinel];
+  ShenandoahPhaseTimings::GCParPhases const _phase;
+  ShenandoahPhaseTimings* const _timings;
+  uint const _worker_id;
 
+  double _start_time;
+  EventGCPhaseParallel _event;
 public:
-  ShenandoahWorkerTimings(uint max_gc_threads);
-
-  // record the time a phase took in seconds
-  void record_time_secs(ShenandoahPhaseTimings::GCParPhases phase, uint worker_i, double secs);
-
-  double average(uint i) const;
-  void reset(uint i);
-  void print() const;
+  ShenandoahWorkerTimingsTracker(ShenandoahPhaseTimings::GCParPhases phase, uint worker_id);
+  ~ShenandoahWorkerTimingsTracker();
 };
 
 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHPHASETIMINGS_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Mon Feb 24 19:03:34 2020 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Fri Mar 06 17:03:42 2020 +0100
@@ -34,7 +34,6 @@
 #include "gc/shenandoah/shenandoahHeap.hpp"
 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
 #include "gc/shenandoah/shenandoahStringDedup.hpp"
-#include "gc/shenandoah/shenandoahTimingTracker.hpp"
 #include "gc/shenandoah/shenandoahVMOperations.hpp"
 #include "jfr/jfr.hpp"
 #include "memory/iterator.hpp"
@@ -49,8 +48,7 @@
 
 void ShenandoahSerialRoot::oops_do(OopClosure* cl, uint worker_id) {
   if (_claimed.try_set()) {
-    ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-    ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id);
+    ShenandoahWorkerTimingsTracker timer(_phase, worker_id);
     _oops_do(cl);
   }
 }
@@ -82,8 +80,7 @@
 
 void ShenandoahWeakSerialRoot::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id) {
   if (_claimed.try_set()) {
-    ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-    ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id);
+    ShenandoahWorkerTimingsTracker timer(_phase, worker_id);
     _weak_oops_do(is_alive, keep_alive);
   }
 }
@@ -115,15 +112,13 @@
 }
 
 void ShenandoahThreadRoots::oops_do(OopClosure* oops_cl, CodeBlobClosure* code_cl, uint worker_id) {
-  ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-  ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id);
+  ShenandoahWorkerTimingsTracker timer(ShenandoahPhaseTimings::ThreadRoots, worker_id);
   ResourceMark rm;
   Threads::possibly_parallel_oops_do(_is_par, oops_cl, code_cl);
 }
 
 void ShenandoahThreadRoots::threads_do(ThreadClosure* tc, uint worker_id) {
-  ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-  ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id);
+  ShenandoahWorkerTimingsTracker timer(ShenandoahPhaseTimings::ThreadRoots, worker_id);
   ResourceMark rm;
   Threads::possibly_parallel_threads_do(_is_par, tc);
 }
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp	Mon Feb 24 19:03:34 2020 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp	Fri Mar 06 17:03:42 2020 +0100
@@ -32,8 +32,8 @@
 #include "gc/shenandoah/shenandoahClosures.inline.hpp"
 #include "gc/shenandoah/shenandoahConcurrentRoots.hpp"
 #include "gc/shenandoah/shenandoahHeuristics.hpp"
+#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
 #include "gc/shenandoah/shenandoahRootProcessor.hpp"
-#include "gc/shenandoah/shenandoahTimingTracker.hpp"
 #include "gc/shenandoah/shenandoahUtils.hpp"
 #include "memory/resourceArea.hpp"
 #include "prims/resolvedMethodTable.hpp"
@@ -50,8 +50,7 @@
   if (CONCURRENT) {
     _itr.oops_do(cl);
   } else {
-    ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-    ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id);
+    ShenandoahWorkerTimingsTracker timer(_phase, worker_id);
     _itr.oops_do(cl);
   }
 }
@@ -67,8 +66,7 @@
 
 template <typename IsAliveClosure, typename KeepAliveClosure>
 void ShenandoahWeakRoot<false /* concurrent */>::weak_oops_do(IsAliveClosure* is_alive, KeepAliveClosure* keep_alive, uint worker_id) {
-  ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-  ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id);
+  ShenandoahWorkerTimingsTracker timer(_phase, worker_id);
   _itr.weak_oops_do(is_alive, keep_alive);
 }
 
@@ -150,8 +148,7 @@
   } else if (CONCURRENT) {
      ClassLoaderDataGraph::always_strong_cld_do(clds);
   } else {
-   ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-   ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
+   ShenandoahWorkerTimingsTracker timer(ShenandoahPhaseTimings::CLDGRoots, worker_id);
    ClassLoaderDataGraph::always_strong_cld_do(clds);
   }
 }
@@ -165,8 +162,7 @@
   } else if (CONCURRENT) {
     ClassLoaderDataGraph::cld_do(clds);
   }  else {
-    ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
+    ShenandoahWorkerTimingsTracker timer(ShenandoahPhaseTimings::CLDGRoots, worker_id);
     ClassLoaderDataGraph::cld_do(clds);
   }
 }
@@ -178,8 +174,7 @@
 
 template <typename ITR>
 void ShenandoahCodeCacheRoots<ITR>::code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id) {
-  ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-  ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id);
+  ShenandoahWorkerTimingsTracker timer(ShenandoahPhaseTimings::CodeCacheRoots, worker_id);
   _coderoots_iterator.possibly_parallel_blobs_do(blob_cl);
 }
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahStringDedup.cpp	Mon Feb 24 19:03:34 2020 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahStringDedup.cpp	Fri Mar 06 17:03:42 2020 +0100
@@ -29,9 +29,9 @@
 #include "gc/shenandoah/shenandoahCollectionSet.inline.hpp"
 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
 #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp"
+#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
 #include "gc/shenandoah/shenandoahStringDedup.hpp"
 #include "gc/shenandoah/shenandoahStrDedupQueue.hpp"
-#include "gc/shenandoah/shenandoahTimingTracker.hpp"
 #include "gc/shenandoah/shenandoahUtils.hpp"
 #include "runtime/thread.hpp"
 
@@ -78,14 +78,13 @@
 
   StringDedupUnlinkOrOopsDoClosure sd_cl(is_alive, cl);
   if (ShenandoahGCPhase::is_root_work_phase()) {
-    ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
     {
-      ShenandoahWorkerTimingsTracker x(worker_times, ShenandoahPhaseTimings::StringDedupQueueRoots, worker_id);
+      ShenandoahWorkerTimingsTracker x(ShenandoahPhaseTimings::StringDedupQueueRoots, worker_id);
       StringDedupQueue::unlink_or_oops_do(&sd_cl);
     }
 
     {
-      ShenandoahWorkerTimingsTracker x(worker_times, ShenandoahPhaseTimings::StringDedupTableRoots, worker_id);
+      ShenandoahWorkerTimingsTracker x(ShenandoahPhaseTimings::StringDedupTableRoots, worker_id);
       StringDedupTable::unlink_or_oops_do(&sd_cl, worker_id);
     }
   } else {
--- a/src/hotspot/share/gc/shenandoah/shenandoahTimingTracker.cpp	Mon Feb 24 19:03:34 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, Red Hat, Inc. 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-
-#include "gc/shenandoah/shenandoahHeap.hpp"
-#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
-#include "gc/shenandoah/shenandoahTimingTracker.hpp"
-#include "gc/shenandoah/shenandoahUtils.hpp"
-#include "runtime/os.hpp"
-
-
-ShenandoahWorkerTimingsTracker::ShenandoahWorkerTimingsTracker(ShenandoahWorkerTimings* worker_times,
-                                                              ShenandoahPhaseTimings::GCParPhases phase, uint worker_id) :
-  _phase(phase), _worker_times(worker_times), _worker_id(worker_id) {
-  if (_worker_times != NULL) {
-    _start_time = os::elapsedTime();
-  }
-}
-
-ShenandoahWorkerTimingsTracker::~ShenandoahWorkerTimingsTracker() {
-  if (_worker_times != NULL) {
-    _worker_times->record_time_secs(_phase, _worker_id, os::elapsedTime() - _start_time);
-  }
-
-  if (ShenandoahGCPhase::is_root_work_phase()) {
-    ShenandoahPhaseTimings::Phase root_phase = ShenandoahGCPhase::current_phase();
-    ShenandoahPhaseTimings::Phase cur_phase = (ShenandoahPhaseTimings::Phase)((int)root_phase + (int)_phase + 1);
-    _event.commit(GCId::current(), _worker_id, ShenandoahPhaseTimings::phase_name(cur_phase));
-  }
-}
-
--- a/src/hotspot/share/gc/shenandoah/shenandoahTimingTracker.hpp	Mon Feb 24 19:03:34 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, Red Hat, Inc. 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHTIMINGTRACKER_HPP
-#define SHARE_GC_SHENANDOAH_SHENANDOAHTIMINGTRACKER_HPP
-
-#include "jfr/jfrEvents.hpp"
-#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
-#include "memory/allocation.hpp"
-
-class ShenandoahWorkerTimingsTracker : public StackObj {
-private:
-  double _start_time;
-  ShenandoahPhaseTimings::GCParPhases _phase;
-  ShenandoahWorkerTimings* _worker_times;
-  uint _worker_id;
-
-  EventGCPhaseParallel _event;
-public:
-    ShenandoahWorkerTimingsTracker(ShenandoahWorkerTimings* worker_times, ShenandoahPhaseTimings::GCParPhases phase, uint worker_id);
-    ~ShenandoahWorkerTimingsTracker();
-};
-
-#endif // SHARE_GC_SHENANDOAH_SHENANDOAHTIMINGTRACKER_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp	Mon Feb 24 19:03:34 2020 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp	Fri Mar 06 17:03:42 2020 +0100
@@ -41,10 +41,10 @@
 #include "gc/shenandoah/shenandoahHeuristics.hpp"
 #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp"
 #include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
+#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
 #include "gc/shenandoah/shenandoahStringDedup.hpp"
 #include "gc/shenandoah/shenandoahTaskqueue.inline.hpp"
-#include "gc/shenandoah/shenandoahTimingTracker.hpp"
 #include "gc/shenandoah/shenandoahTraversalGC.hpp"
 #include "gc/shenandoah/shenandoahUtils.hpp"
 #include "gc/shenandoah/shenandoahVerifier.hpp"
@@ -283,8 +283,7 @@
     }
 
     {
-      ShenandoahWorkerTimings *worker_times = _heap->phase_timings()->worker_times();
-      ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::FinishQueues, worker_id);
+      ShenandoahWorkerTimingsTracker timer(ShenandoahPhaseTimings::FinishQueues, worker_id);
 
       // Step 3: Finally drain all outstanding work in queues.
       traversal_gc->main_loop(worker_id, _terminator, false);
--- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp	Mon Feb 24 19:03:34 2020 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp	Fri Mar 06 17:03:42 2020 +0100
@@ -108,12 +108,11 @@
           "Must be set by these threads");
   _parent_phase = _current_phase;
   _current_phase = phase;
-
-  _heap->phase_timings()->record_phase_start(_phase);
+  _start = os::elapsedTime();
 }
 
 ShenandoahGCPhase::~ShenandoahGCPhase() {
-  _heap->phase_timings()->record_phase_end(_phase);
+  _heap->phase_timings()->record_phase_time(_phase, os::elapsedTime() - _start);
   _current_phase = _parent_phase;
 }
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp	Mon Feb 24 19:03:34 2020 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp	Fri Mar 06 17:03:42 2020 +0100
@@ -62,6 +62,8 @@
   ShenandoahHeap* const _heap;
   const ShenandoahPhaseTimings::Phase   _phase;
   ShenandoahPhaseTimings::Phase         _parent_phase;
+  double _start;
+
 public:
   ShenandoahGCPhase(ShenandoahPhaseTimings::Phase phase);
   ~ShenandoahGCPhase();