1 /*
   2  * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  *
  22  */
  23 
  24 #include "precompiled.hpp"
  25 
  26 #include "gc/shared/workerDataArray.inline.hpp"
  27 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
  28 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
  29 #include "gc/shenandoah/shenandoahHeap.hpp"
  30 #include "utilities/ostream.hpp"
  31 
  32 ShenandoahPhaseTimings::ShenandoahPhaseTimings() : _policy(NULL) {
  33   _worker_times = new ShenandoahWorkerTimings(MAX2(ConcGCThreads, ParallelGCThreads));
  34   _policy = ShenandoahHeap::heap()->shenandoahPolicy();
  35   assert(_policy != NULL, "Can not be NULL");
  36   init_phase_names();
  37 }
  38 
  39 void ShenandoahPhaseTimings::record_phase_start(Phase phase) {
  40   _timing_data[phase]._start = os::elapsedTime();
  41 }
  42 
  43 void ShenandoahPhaseTimings::record_phase_end(Phase phase) {
  44   assert(_policy != NULL, "Not yet initialized");
  45   double end = os::elapsedTime();
  46   double elapsed = end - _timing_data[phase]._start;
  47   if (!_policy->is_at_shutdown()) {
  48     _timing_data[phase]._secs.add(elapsed);
  49   }
  50   _policy->record_phase_time(phase, elapsed);
  51 }
  52 
  53 void ShenandoahPhaseTimings::record_phase_time(Phase phase, jint time_us) {
  54   assert(_policy != NULL, "Not yet initialized");
  55   if (!_policy->is_at_shutdown()) {
  56     _timing_data[phase]._secs.add((double)time_us / 1000 / 1000);
  57   }
  58 }
  59 
  60 void ShenandoahPhaseTimings::record_workers_start(Phase phase) {
  61   for (uint i = 0; i < GCParPhasesSentinel; i++) {
  62     _worker_times->reset(i);
  63   }
  64 }
  65 
  66 void ShenandoahPhaseTimings::record_workers_end(Phase phase) {
  67   if (_policy->is_at_shutdown()) {
  68     // Do not record the past-shutdown events
  69     return;
  70   }
  71 
  72   guarantee(phase == init_evac ||
  73             phase == scan_roots ||
  74             phase == update_roots ||
  75             phase == init_partial_gc_work ||
  76             phase == final_partial_gc_work ||
  77             phase == init_traversal_gc_work ||
  78             phase == final_traversal_gc_work ||
  79             phase == final_traversal_update_roots ||
  80             phase == final_update_refs_roots ||
  81             phase == full_gc_roots ||
  82             phase == _num_phases,
  83             "only in these phases we can add per-thread phase times");
  84   if (phase != _num_phases) {
  85     // Merge _phase_time to counters below the given phase.
  86     for (uint i = 0; i < GCParPhasesSentinel; i++) {
  87       double t = _worker_times->average(i);
  88       _timing_data[phase + i + 1]._secs.add(t);
  89     }
  90   }
  91 }
  92 
  93 void ShenandoahPhaseTimings::print_on(outputStream* out) const {
  94   out->cr();
  95   out->print_cr("GC STATISTICS:");
  96   out->print_cr("  \"(G)\" (gross) pauses include VM time: time to notify and block threads, do the pre-");
  97   out->print_cr("        and post-safepoint housekeeping. Use -XX:+PrintSafepointStatistics to dissect.");
  98   out->print_cr("  \"(N)\" (net) pauses are the times spent in the actual GC code.");
  99   out->print_cr("  \"a\" is average time for each phase, look at levels to see if average makes sense.");
 100   out->print_cr("  \"lvls\" are quantiles: 0%% (minimum), 25%%, 50%% (median), 75%%, 100%% (maximum).");
 101   out->cr();
 102 
 103   for (uint i = 0; i < _num_phases; i++) {
 104     if (_timing_data[i]._secs.maximum() != 0) {
 105       print_summary_sd(out, _phase_names[i], &(_timing_data[i]._secs));
 106     }
 107   }
 108 }
 109 
 110 void ShenandoahPhaseTimings::print_summary_sd(outputStream* out, const char* str, const HdrSeq* seq) const {
 111   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)",
 112           str,
 113           seq->sum(),
 114           seq->avg() * 1000000.0,
 115           seq->num(),
 116           seq->percentile(0)  * 1000000.0,
 117           seq->percentile(25) * 1000000.0,
 118           seq->percentile(50) * 1000000.0,
 119           seq->percentile(75) * 1000000.0,
 120           seq->maximum() * 1000000.0
 121   );
 122 }
 123 
 124 void ShenandoahPhaseTimings::init_phase_names() {
 125   _phase_names[total_pause]                     = "Total Pauses (N)";
 126   _phase_names[total_pause_gross]               = "Total Pauses (G)";
 127   _phase_names[init_mark]                       = "Pause Init Mark (N)";
 128   _phase_names[init_mark_gross]                 = "Pause Init Mark (G)";
 129   _phase_names[final_mark]                      = "Pause Final Mark (N)";
 130   _phase_names[final_mark_gross]                = "Pause Final Mark (G)";
 131   _phase_names[final_evac]                      = "Pause Final Evac (N)";
 132   _phase_names[final_evac_gross]                = "Pause Final Evac (G)";
 133   _phase_names[accumulate_stats]                = "  Accumulate Stats";
 134   _phase_names[make_parsable]                   = "  Make Parsable";
 135   _phase_names[clear_liveness]                  = "  Clear Liveness";
 136   _phase_names[resize_tlabs]                    = "  Resize TLABs";
 137   _phase_names[finish_queues]                   = "  Finish Queues";
 138   _phase_names[weakrefs]                        = "  Weak References";
 139   _phase_names[weakrefs_process]                = "    Process";
 140   _phase_names[weakrefs_enqueue]                = "    Enqueue";
 141   _phase_names[purge]                           = "  System Purge";
 142   _phase_names[purge_class_unload]              = "    Unload Classes";
 143   _phase_names[purge_par]                       = "    Parallel Cleanup";
 144   _phase_names[purge_par_codecache]             = "      Code Cache";
 145   _phase_names[purge_par_symbstring]            = "      String/Symbol Tables";
 146   _phase_names[purge_par_rmt]                   = "      Resolved Methods";
 147   _phase_names[purge_par_classes]               = "      Clean Classes";
 148   _phase_names[purge_par_sync]                  = "      Synchronization";
 149   _phase_names[purge_par_string_dedup]          = "    String Dedup";
 150   _phase_names[purge_cldg]                      = "    CLDG";
 151   _phase_names[prepare_evac]                    = "  Prepare Evacuation";
 152 
 153   _phase_names[scan_roots]                      = "  Scan Roots";
 154   _phase_names[scan_thread_roots]               = "    S: Thread Roots";
 155   _phase_names[scan_code_roots]                 = "    S: Code Cache Roots";
 156   _phase_names[scan_string_table_roots]         = "    S: String Table Roots";
 157   _phase_names[scan_universe_roots]             = "    S: Universe Roots";
 158   _phase_names[scan_jni_roots]                  = "    S: JNI Roots";
 159   _phase_names[scan_jni_weak_roots]             = "    S: JNI Weak Roots";
 160   _phase_names[scan_synchronizer_roots]         = "    S: Synchronizer Roots";
 161   _phase_names[scan_flat_profiler_roots]        = "    S: Flat Profiler Roots";
 162   _phase_names[scan_management_roots]           = "    S: Management Roots";
 163   _phase_names[scan_system_dictionary_roots]    = "    S: System Dict Roots";
 164   _phase_names[scan_cldg_roots]                 = "    S: CLDG Roots";
 165   _phase_names[scan_jvmti_roots]                = "    S: JVMTI Roots";
 166   _phase_names[scan_string_dedup_roots]         = "    S: String Dedup Roots";
 167   _phase_names[scan_finish_queues]              = "    S: Finish Queues";
 168 
 169   _phase_names[update_roots]                    = "  Update Roots";
 170   _phase_names[update_thread_roots]             = "    U: Thread Roots";
 171   _phase_names[update_code_roots]               = "    U: Code Cache Roots";
 172   _phase_names[update_string_table_roots]       = "    U: String Table Roots";
 173   _phase_names[update_universe_roots]           = "    U: Universe Roots";
 174   _phase_names[update_jni_roots]                = "    U: JNI Roots";
 175   _phase_names[update_jni_weak_roots]           = "    U: JNI Weak Roots";
 176   _phase_names[update_synchronizer_roots]       = "    U: Synchronizer Roots";
 177   _phase_names[update_flat_profiler_roots]      = "    U: Flat Profiler Roots";
 178   _phase_names[update_management_roots]         = "    U: Management Roots";
 179   _phase_names[update_system_dictionary_roots]  = "    U: System Dict Roots";
 180   _phase_names[update_cldg_roots]               = "    U: CLDG Roots";
 181   _phase_names[update_jvmti_roots]              = "    U: JVMTI Roots";
 182   _phase_names[update_string_dedup_roots]       = "    U: String Dedup Roots";
 183   _phase_names[update_finish_queues]            = "    U: Finish Queues";
 184 
 185   _phase_names[init_evac]                       = "  Initial Evacuation";
 186   _phase_names[evac_thread_roots]               = "    E: Thread Roots";
 187   _phase_names[evac_code_roots]                 = "    E: Code Cache Roots";
 188   _phase_names[evac_string_table_roots]         = "    E: String Table Roots";
 189   _phase_names[evac_universe_roots]             = "    E: Universe Roots";
 190   _phase_names[evac_jni_roots]                  = "    E: JNI Roots";
 191   _phase_names[evac_jni_weak_roots]             = "    E: JNI Weak Roots";
 192   _phase_names[evac_synchronizer_roots]         = "    E: Synchronizer Roots";
 193   _phase_names[evac_flat_profiler_roots]        = "    E: Flat Profiler Roots";
 194   _phase_names[evac_management_roots]           = "    E: Management Roots";
 195   _phase_names[evac_system_dictionary_roots]    = "    E: System Dict Roots";
 196   _phase_names[evac_cldg_roots]                 = "    E: CLDG Roots";
 197   _phase_names[evac_jvmti_roots]                = "    E: JVMTI Roots";
 198   _phase_names[evac_string_dedup_roots]         = "    E: String Dedup Roots";
 199   _phase_names[evac_finish_queues]              = "    E: Finish Queues";
 200 
 201   _phase_names[recycle_regions]                 = "  Recycle regions";
 202 
 203   _phase_names[degen_gc_gross]                  = "Pause Degenerated GC (G)";
 204   _phase_names[degen_gc]                        = "Pause Degenerated GC (N)";
 205 
 206   _phase_names[full_gc_gross]                   = "Pause Full GC (G)";
 207   _phase_names[full_gc]                         = "Pause Full GC (N)";
 208   _phase_names[full_gc_heapdumps]               = "  Heap Dumps";
 209   _phase_names[full_gc_prepare]                 = "  Prepare";
 210   _phase_names[full_gc_roots]                   = "  Roots";
 211   _phase_names[full_gc_thread_roots]            = "    F: Thread Roots";
 212   _phase_names[full_gc_code_roots]              = "    F: Code Cache Roots";
 213   _phase_names[full_gc_string_table_roots]      = "    F: String Table Roots";
 214   _phase_names[full_gc_universe_roots]          = "    F: Universe Roots";
 215   _phase_names[full_gc_jni_roots]               = "    F: JNI Roots";
 216   _phase_names[full_gc_jni_weak_roots]          = "    F: JNI Weak Roots";
 217   _phase_names[full_gc_synchronizer_roots]      = "    F: Synchronizer Roots";
 218   _phase_names[full_gc_flat_profiler_roots]     = "    F: Flat Profiler Roots";
 219   _phase_names[full_gc_management_roots]        = "    F: Management Roots";
 220   _phase_names[full_gc_system_dictionary_roots] = "    F: System Dict Roots";
 221   _phase_names[full_gc_cldg_roots]              = "    F: CLDG Roots";
 222   _phase_names[full_gc_jvmti_roots]             = "    F: JVMTI Roots";
 223   _phase_names[full_gc_string_dedup_roots]      = "    F: String Dedup Roots";
 224   _phase_names[full_gc_finish_queues]           = "    F: Finish Queues";
 225   _phase_names[full_gc_mark]                    = "  Mark";
 226   _phase_names[full_gc_mark_finish_queues]      = "    Finish Queues";
 227   _phase_names[full_gc_weakrefs]                = "    Weak References";
 228   _phase_names[full_gc_weakrefs_process]        = "      Process";
 229   _phase_names[full_gc_weakrefs_enqueue]        = "      Enqueue";
 230   _phase_names[full_gc_purge]                   = "    System Purge";
 231   _phase_names[full_gc_purge_class_unload]      = "      Unload Classes";
 232   _phase_names[full_gc_purge_par]               = "    Parallel Cleanup";
 233   _phase_names[full_gc_purge_par_codecache]     = "      Code Cache";
 234   _phase_names[full_gc_purge_par_symbstring]    = "      String/Symbol Tables";
 235   _phase_names[full_gc_purge_par_rmt]           = "      Resolved Methods";
 236   _phase_names[full_gc_purge_par_classes]       = "      Clean Classes";
 237   _phase_names[full_gc_purge_par_sync]          = "      Synchronization";
 238   _phase_names[full_gc_purge_cldg]              = "      CLDG";
 239   _phase_names[full_gc_purge_par_string_dedup]      = "    Purge String Dedup";
 240   _phase_names[full_gc_calculate_addresses]     = "  Calculate Addresses";
 241   _phase_names[full_gc_calculate_addresses_regular] = "    Regular Objects";
 242   _phase_names[full_gc_calculate_addresses_humong]  = "    Humongous Objects";
 243   _phase_names[full_gc_adjust_pointers]         = "  Adjust Pointers";
 244   _phase_names[full_gc_copy_objects]            = "  Copy Objects";
 245   _phase_names[full_gc_copy_objects_regular]    = "    Regular Objects";
 246   _phase_names[full_gc_copy_objects_humong]     = "    Humongous Objects";
 247   _phase_names[full_gc_update_str_dedup_table]  = "  Update String Dedup Table";
 248   _phase_names[full_gc_resize_tlabs]            = "  Resize TLABs";
 249 
 250   _phase_names[init_partial_gc_gross]           = "Pause Init Partial (G)";
 251   _phase_names[init_partial_gc]                 = "Pause Init Partial (N)";
 252   _phase_names[partial_gc_prepare]              = "  Prepare";
 253   _phase_names[init_partial_gc_work]            = "  Work";
 254   _phase_names[init_partial_gc_thread_roots]        = "    PI: Thread Roots";
 255   _phase_names[init_partial_gc_code_roots]          = "    PI: Code Cache Roots";
 256   _phase_names[init_partial_gc_string_table_roots]  = "    PI: String Table Roots";
 257   _phase_names[init_partial_gc_universe_roots]      = "    PI: Universe Roots";
 258   _phase_names[init_partial_gc_jni_roots]           = "    PI: JNI Roots";
 259   _phase_names[init_partial_gc_jni_weak_roots]      = "    PI: JNI Weak Roots";
 260   _phase_names[init_partial_gc_synchronizer_roots]  = "    PI: Synchronizer Roots";
 261   _phase_names[init_partial_gc_flat_profiler_roots] = "    PI: Flat Profiler Roots";
 262   _phase_names[init_partial_gc_management_roots]    = "    PI: Management Roots";
 263   _phase_names[init_partial_gc_system_dict_roots]   = "    PI: System Dict Roots";
 264   _phase_names[init_partial_gc_cldg_roots]          = "    PI: CLDG Roots";
 265   _phase_names[init_partial_gc_jvmti_roots]         = "    PI: JVMTI Roots";
 266   _phase_names[init_partial_gc_string_dedup_roots]  = "    PI: String Dedup Roots";
 267   _phase_names[init_partial_gc_finish_queues]       = "    PI: Finish Queues";
 268   _phase_names[final_partial_gc_gross]          = "Pause Final Partial (G)";
 269   _phase_names[final_partial_gc]                = "Pause Final Partial (N)";
 270   _phase_names[final_partial_gc_work]           = "  Work";
 271   _phase_names[final_partial_gc_thread_roots]        = "    PF: Thread Roots";
 272   _phase_names[final_partial_gc_code_roots]          = "    PF: Code Cache Roots";
 273   _phase_names[final_partial_gc_string_table_roots]  = "    PF: String Table Roots";
 274   _phase_names[final_partial_gc_universe_roots]      = "    PF: Universe Roots";
 275   _phase_names[final_partial_gc_jni_roots]           = "    PF: JNI Roots";
 276   _phase_names[final_partial_gc_jni_weak_roots]      = "    PF: JNI Weak Roots";
 277   _phase_names[final_partial_gc_synchronizer_roots]  = "    PF: Synchronizer Roots";
 278   _phase_names[final_partial_gc_flat_profiler_roots] = "    PF: Flat Profiler Roots";
 279   _phase_names[final_partial_gc_management_roots]    = "    PF: Management Roots";
 280   _phase_names[final_partial_gc_system_dict_roots]   = "    PF: System Dict Roots";
 281   _phase_names[final_partial_gc_cldg_roots]          = "    PF: CLDG Roots";
 282   _phase_names[final_partial_gc_jvmti_roots]         = "    PF: JVMTI Roots";
 283   _phase_names[final_partial_gc_string_dedup_roots]  = "    PF: String Dedup Roots";
 284   _phase_names[final_partial_gc_finish_queues]       = "    PF: Finish Queues";
 285 
 286   _phase_names[partial_gc_cleanup]              = "  Cleanup";
 287 
 288   _phase_names[init_traversal_gc_gross]           = "Pause Init Traversal (G)";
 289   _phase_names[init_traversal_gc]                 = "Pause Init Traversal (N)";
 290   _phase_names[traversal_gc_prepare]              = "  Prepare";
 291   _phase_names[init_traversal_gc_work]            = "  Work";
 292   _phase_names[init_traversal_gc_thread_roots]        = "    TI: Thread Roots";
 293   _phase_names[init_traversal_gc_code_roots]          = "    TI: Code Cache Roots";
 294   _phase_names[init_traversal_gc_string_table_roots]  = "    TI: String Table Roots";
 295   _phase_names[init_traversal_gc_universe_roots]      = "    TI: Universe Roots";
 296   _phase_names[init_traversal_gc_jni_roots]           = "    TI: JNI Roots";
 297   _phase_names[init_traversal_gc_jni_weak_roots]      = "    TI: JNI Weak Roots";
 298   _phase_names[init_traversal_gc_synchronizer_roots]  = "    TI: Synchronizer Roots";
 299   _phase_names[init_traversal_gc_flat_profiler_roots] = "    TI: Flat Profiler Roots";
 300   _phase_names[init_traversal_gc_management_roots]    = "    TI: Management Roots";
 301   _phase_names[init_traversal_gc_system_dict_roots]   = "    TI: System Dict Roots";
 302   _phase_names[init_traversal_gc_cldg_roots]          = "    TI: CLDG Roots";
 303   _phase_names[init_traversal_gc_jvmti_roots]         = "    TI: JVMTI Roots";
 304   _phase_names[init_traversal_gc_string_dedup_roots]  = "    TI: String Dedup Roots";
 305   _phase_names[init_traversal_gc_finish_queues]       = "    TI: Finish Queues";
 306   _phase_names[final_traversal_gc_gross]          = "Pause Final Traversal (G)";
 307   _phase_names[final_traversal_gc]                = "Pause Final Traversal (N)";
 308   _phase_names[final_traversal_gc_work]           = "  Work";
 309   _phase_names[final_traversal_gc_thread_roots]        = "    TF: Thread Roots";
 310   _phase_names[final_traversal_gc_code_roots]          = "    TF: Code Cache Roots";
 311   _phase_names[final_traversal_gc_string_table_roots]  = "    TF: String Table Roots";
 312   _phase_names[final_traversal_gc_universe_roots]      = "    TF: Universe Roots";
 313   _phase_names[final_traversal_gc_jni_roots]           = "    TF: JNI Roots";
 314   _phase_names[final_traversal_gc_jni_weak_roots]      = "    TF: JNI Weak Roots";
 315   _phase_names[final_traversal_gc_synchronizer_roots]  = "    TF: Synchronizer Roots";
 316   _phase_names[final_traversal_gc_flat_profiler_roots] = "    TF: Flat Profiler Roots";
 317   _phase_names[final_traversal_gc_management_roots]    = "    TF: Management Roots";
 318   _phase_names[final_traversal_gc_system_dict_roots]   = "    TF: System Dict Roots";
 319   _phase_names[final_traversal_gc_cldg_roots]          = "    TF: CLDG Roots";
 320   _phase_names[final_traversal_gc_jvmti_roots]         = "    TF: JVMTI Roots";
 321   _phase_names[final_traversal_gc_string_dedup_roots]  = "    TF: String Dedup Roots";
 322   _phase_names[final_traversal_gc_finish_queues]       = "    TF: Finish Queues";
 323   _phase_names[final_traversal_update_roots]           = "  Update Roots";
 324   _phase_names[final_traversal_update_thread_roots]        = "    TU: Thread Roots";
 325   _phase_names[final_traversal_update_code_roots]          = "    TU: Code Cache Roots";
 326   _phase_names[final_traversal_update_string_table_roots]  = "    TU: String Table Roots";
 327   _phase_names[final_traversal_update_universe_roots]      = "    TU: Universe Roots";
 328   _phase_names[final_traversal_update_jni_roots]           = "    TU: JNI Roots";
 329   _phase_names[final_traversal_update_jni_weak_roots]      = "    TU: JNI Weak Roots";
 330   _phase_names[final_traversal_update_synchronizer_roots]  = "    TU: Synchronizer Roots";
 331   _phase_names[final_traversal_update_flat_profiler_roots] = "    TU: Flat Profiler Roots";
 332   _phase_names[final_traversal_update_management_roots]    = "    TU: Management Roots";
 333   _phase_names[final_traversal_update_system_dict_roots]   = "    TU: System Dict Roots";
 334   _phase_names[final_traversal_update_cldg_roots]          = "    TU: CLDG Roots";
 335   _phase_names[final_traversal_update_jvmti_roots]         = "    TU: JVMTI Roots";
 336   _phase_names[final_traversal_update_string_dedup_roots]  = "    TU: String Dedup Roots";
 337   _phase_names[final_traversal_update_finish_queues]       = "    TU: Finish Queues";
 338 
 339   _phase_names[traversal_gc_cleanup]              = "  Cleanup";
 340 
 341   _phase_names[pause_other]                     = "Pause Other";
 342 
 343   _phase_names[conc_mark]                       = "Concurrent Marking";
 344   _phase_names[conc_preclean]                   = "Concurrent Precleaning";
 345   _phase_names[conc_evac]                       = "Concurrent Evacuation";
 346   _phase_names[conc_cleanup]                    = "Concurrent Cleanup";
 347   _phase_names[conc_cleanup_recycle]            = "  Recycle";
 348   _phase_names[conc_cleanup_reset_bitmaps]      = "  Reset Bitmaps";
 349   _phase_names[conc_other]                      = "Concurrent Other";
 350   _phase_names[conc_partial]                    = "Concurrent Partial";
 351   _phase_names[conc_traversal]                  = "Concurrent Traversal";
 352 
 353   _phase_names[init_update_refs_gross]          = "Pause Init  Update Refs (G)";
 354   _phase_names[init_update_refs]                = "Pause Init  Update Refs (N)";
 355   _phase_names[conc_update_refs]                = "Concurrent Update Refs";
 356   _phase_names[final_update_refs_gross]         = "Pause Final Update Refs (G)";
 357   _phase_names[final_update_refs]               = "Pause Final Update Refs (N)";
 358 
 359   _phase_names[final_update_refs_finish_work]          = "  Finish Work";
 360   _phase_names[final_update_refs_roots]                = "  Update Roots";
 361   _phase_names[final_update_refs_thread_roots]         = "    UR: Thread Roots";
 362   _phase_names[final_update_refs_code_roots]           = "    UR: Code Cache Roots";
 363   _phase_names[final_update_refs_string_table_roots]   = "    UR: String Table Roots";
 364   _phase_names[final_update_refs_universe_roots]       = "    UR: Universe Roots";
 365   _phase_names[final_update_refs_jni_roots]            = "    UR: JNI Roots";
 366   _phase_names[final_update_refs_jni_weak_roots]       = "    UR: JNI Weak Roots";
 367   _phase_names[final_update_refs_synchronizer_roots]   = "    UR: Synchronizer Roots";
 368   _phase_names[final_update_refs_flat_profiler_roots]  = "    UR: Flat Profiler Roots";
 369   _phase_names[final_update_refs_management_roots]     = "    UR: Management Roots";
 370   _phase_names[final_update_refs_system_dict_roots]    = "    UR: System Dict Roots";
 371   _phase_names[final_update_refs_cldg_roots]           = "    UR: CLDG Roots";
 372   _phase_names[final_update_refs_jvmti_roots]          = "    UR: JVMTI Roots";
 373   _phase_names[final_update_refs_string_dedup_roots]   = "    UR: String Dedup Roots";
 374   _phase_names[final_update_refs_finish_queues]        = "    UR: Finish Queues";
 375   _phase_names[final_update_refs_recycle]              = "  Recycle";
 376 }
 377 
 378 ShenandoahWorkerTimings::ShenandoahWorkerTimings(uint max_gc_threads) :
 379         _max_gc_threads(max_gc_threads)
 380 {
 381   assert(max_gc_threads > 0, "Must have some GC threads");
 382 
 383   // Root scanning phases
 384   _gc_par_phases[ShenandoahPhaseTimings::ThreadRoots]             = new WorkerDataArray<double>(max_gc_threads, "Thread Roots (ms):");
 385   _gc_par_phases[ShenandoahPhaseTimings::CodeCacheRoots]          = new WorkerDataArray<double>(max_gc_threads, "CodeCache Roots (ms):");
 386   _gc_par_phases[ShenandoahPhaseTimings::StringTableRoots]        = new WorkerDataArray<double>(max_gc_threads, "StringTable Roots (ms):");
 387   _gc_par_phases[ShenandoahPhaseTimings::UniverseRoots]           = new WorkerDataArray<double>(max_gc_threads, "Universe Roots (ms):");
 388   _gc_par_phases[ShenandoahPhaseTimings::JNIRoots]                = new WorkerDataArray<double>(max_gc_threads, "JNI Handles Roots (ms):");
 389   _gc_par_phases[ShenandoahPhaseTimings::JNIWeakRoots]            = new WorkerDataArray<double>(max_gc_threads, "JNI Weak Roots (ms):");
 390   _gc_par_phases[ShenandoahPhaseTimings::ObjectSynchronizerRoots] = new WorkerDataArray<double>(max_gc_threads, "ObjectSynchronizer Roots (ms):");
 391   _gc_par_phases[ShenandoahPhaseTimings::FlatProfilerRoots]       = new WorkerDataArray<double>(max_gc_threads, "FlatProfiler Roots (ms):");
 392   _gc_par_phases[ShenandoahPhaseTimings::ManagementRoots]         = new WorkerDataArray<double>(max_gc_threads, "Management Roots (ms):");
 393   _gc_par_phases[ShenandoahPhaseTimings::SystemDictionaryRoots]   = new WorkerDataArray<double>(max_gc_threads, "SystemDictionary Roots (ms):");
 394   _gc_par_phases[ShenandoahPhaseTimings::CLDGRoots]               = new WorkerDataArray<double>(max_gc_threads, "CLDG Roots (ms):");
 395   _gc_par_phases[ShenandoahPhaseTimings::JVMTIRoots]              = new WorkerDataArray<double>(max_gc_threads, "JVMTI Roots (ms):");
 396   _gc_par_phases[ShenandoahPhaseTimings::StringDedupRoots]        = new WorkerDataArray<double>(max_gc_threads, "String Dedup Roots (ms):");
 397   _gc_par_phases[ShenandoahPhaseTimings::FinishQueues]            = new WorkerDataArray<double>(max_gc_threads, "Finish Queues (ms):");
 398 }
 399 
 400 // record the time a phase took in seconds
 401 void ShenandoahWorkerTimings::record_time_secs(ShenandoahPhaseTimings::GCParPhases phase, uint worker_i, double secs) {
 402   _gc_par_phases[phase]->set(worker_i, secs);
 403 }
 404 
 405 double ShenandoahWorkerTimings::average(uint i) {
 406   return _gc_par_phases[i]->average();
 407 }
 408 void ShenandoahWorkerTimings::reset(uint i) {
 409   _gc_par_phases[i]->reset();
 410 }
 411 
 412 void ShenandoahWorkerTimings::print() {
 413   for (uint i = 0; i < ShenandoahPhaseTimings::GCParPhasesSentinel; i++) {
 414     _gc_par_phases[i]->print_summary_on(tty);
 415   }
 416 }
 417 
 418 ShenandoahWorkerTimingsTracker::ShenandoahWorkerTimingsTracker(ShenandoahWorkerTimings* worker_times,
 419                                                                ShenandoahPhaseTimings::GCParPhases phase, uint worker_id) :
 420         _worker_times(worker_times), _phase(phase), _worker_id(worker_id) {
 421   if (_worker_times != NULL) {
 422     _start_time = os::elapsedTime();
 423   }
 424 }
 425 
 426 ShenandoahWorkerTimingsTracker::~ShenandoahWorkerTimingsTracker() {
 427   if (_worker_times != NULL) {
 428     _worker_times->record_time_secs(_phase, _worker_id, os::elapsedTime() - _start_time);
 429   }
 430 }