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 "gc/shenandoah/shenandoahHeuristics.hpp"
  31 #include "utilities/ostream.hpp"
  32 
  33 ShenandoahPhaseTimings::ShenandoahPhaseTimings() : _policy(NULL) {
  34   uint max_workers = MAX2(ConcGCThreads, ParallelGCThreads);
  35   _worker_times = new ShenandoahWorkerTimings(max_workers);
  36   _termination_times = new ShenandoahTerminationTimings(max_workers);
  37   _policy = ShenandoahHeap::heap()->shenandoahPolicy();
  38   assert(_policy != NULL, "Can not be NULL");
  39   init_phase_names();
  40 }
  41 
  42 void ShenandoahPhaseTimings::record_phase_start(Phase phase) {
  43   _timing_data[phase]._start = os::elapsedTime();
  44 }
  45 
  46 void ShenandoahPhaseTimings::record_phase_end(Phase phase) {
  47   assert(_policy != NULL, "Not yet initialized");
  48   double end = os::elapsedTime();
  49   double elapsed = end - _timing_data[phase]._start;
  50   if (!_policy->is_at_shutdown()) {
  51     _timing_data[phase]._secs.add(elapsed);
  52   }
  53   ShenandoahHeap::heap()->heuristics()->record_phase_time(phase, elapsed);
  54 }
  55 
  56 void ShenandoahPhaseTimings::record_phase_time(Phase phase, jint time_us) {
  57   assert(_policy != NULL, "Not yet initialized");
  58   if (!_policy->is_at_shutdown()) {
  59     _timing_data[phase]._secs.add((double)time_us / 1000 / 1000);
  60   }
  61 }
  62 
  63 void ShenandoahPhaseTimings::record_workers_start(Phase phase) {
  64   for (uint i = 0; i < GCParPhasesSentinel; i++) {
  65     _worker_times->reset(i);
  66   }
  67 }
  68 
  69 void ShenandoahPhaseTimings::record_workers_end(Phase phase) {
  70   if (_policy->is_at_shutdown()) {
  71     // Do not record the past-shutdown events
  72     return;
  73   }
  74 
  75   guarantee(phase == init_evac ||
  76             phase == scan_roots ||
  77             phase == update_roots ||
  78             phase == init_traversal_gc_work ||
  79             phase == final_traversal_gc_work ||
  80             phase == final_traversal_update_roots ||
  81             phase == final_update_refs_roots ||
  82             phase == full_gc_roots ||
  83             phase == degen_gc_update_roots ||
  84             phase == _num_phases,
  85             "only in these phases we can add per-thread phase times");
  86   if (phase != _num_phases) {
  87     // Merge _phase_time to counters below the given phase.
  88     for (uint i = 0; i < GCParPhasesSentinel; i++) {
  89       double t = _worker_times->average(i);
  90       _timing_data[phase + i + 1]._secs.add(t);
  91     }
  92   }
  93 }
  94 
  95 void ShenandoahPhaseTimings::print_on(outputStream* out) const {
  96   out->cr();
  97   out->print_cr("GC STATISTICS:");
  98   out->print_cr("  \"(G)\" (gross) pauses include VM time: time to notify and block threads, do the pre-");
  99   out->print_cr("        and post-safepoint housekeeping. Use -XX:+PrintSafepointStatistics to dissect.");
 100   out->print_cr("  \"(N)\" (net) pauses are the times spent in the actual GC code.");
 101   out->print_cr("  \"a\" is average time for each phase, look at levels to see if average makes sense.");
 102   out->print_cr("  \"lvls\" are quantiles: 0%% (minimum), 25%%, 50%% (median), 75%%, 100%% (maximum).");
 103   out->cr();
 104 
 105   for (uint i = 0; i < _num_phases; i++) {
 106     if (_timing_data[i]._secs.maximum() != 0) {
 107       print_summary_sd(out, _phase_names[i], &(_timing_data[i]._secs));
 108     }
 109   }
 110 }
 111 
 112 void ShenandoahPhaseTimings::print_summary_sd(outputStream* out, const char* str, const HdrSeq* seq) const {
 113   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)",
 114           str,
 115           seq->sum(),
 116           seq->avg() * 1000000.0,
 117           seq->num(),
 118           seq->percentile(0)  * 1000000.0,
 119           seq->percentile(25) * 1000000.0,
 120           seq->percentile(50) * 1000000.0,
 121           seq->percentile(75) * 1000000.0,
 122           seq->maximum() * 1000000.0
 123   );
 124 }
 125 
 126 void ShenandoahPhaseTimings::init_phase_names() {
 127   _phase_names[total_pause]                     = "Total Pauses (N)";
 128   _phase_names[total_pause_gross]               = "Total Pauses (G)";
 129   _phase_names[init_mark]                       = "Pause Init Mark (N)";
 130   _phase_names[init_mark_gross]                 = "Pause Init Mark (G)";
 131   _phase_names[final_mark]                      = "Pause Final Mark (N)";
 132   _phase_names[final_mark_gross]                = "Pause Final Mark (G)";
 133   _phase_names[final_evac]                      = "Pause Final Evac (N)";
 134   _phase_names[final_evac_gross]                = "Pause Final Evac (G)";
 135   _phase_names[accumulate_stats]                = "  Accumulate Stats";
 136   _phase_names[make_parsable]                   = "  Make Parsable";
 137   _phase_names[clear_liveness]                  = "  Clear Liveness";
 138   _phase_names[resize_tlabs]                    = "  Resize TLABs";
 139   _phase_names[finish_queues]                   = "  Finish Queues";
 140   _phase_names[termination]                     = "    Termination";
 141   _phase_names[weakrefs]                        = "  Weak References";
 142   _phase_names[weakrefs_process]                = "    Process";
 143   _phase_names[weakrefs_termination]            = "      Termination";
 144   _phase_names[purge]                           = "  System Purge";
 145   _phase_names[purge_class_unload]              = "    Unload Classes";
 146   _phase_names[purge_par]                       = "    Parallel Cleanup";
 147   _phase_names[purge_par_codecache]             = "      Code Cache";
 148   _phase_names[purge_par_symbstring]            = "      String/Symbol Tables";
 149   _phase_names[purge_par_classes]               = "      Clean Classes";
 150   _phase_names[purge_par_sync]                  = "      Synchronization";
 151   _phase_names[purge_string_dedup]              = "    String Dedup";
 152   _phase_names[purge_cldg]                      = "    CLDG";
 153   _phase_names[complete_liveness]               = "  Complete Liveness";
 154   _phase_names[prepare_evac]                    = "  Prepare Evacuation";
 155 
 156   _phase_names[scan_roots]                      = "  Scan Roots";
 157   _phase_names[scan_thread_roots]               = "    S: Thread Roots";
 158   _phase_names[scan_code_roots]                 = "    S: Code Cache Roots";
 159   _phase_names[scan_string_table_roots]         = "    S: String Table Roots";
 160   _phase_names[scan_universe_roots]             = "    S: Universe Roots";
 161   _phase_names[scan_jni_roots]                  = "    S: JNI Roots";
 162   _phase_names[scan_jni_weak_roots]             = "    S: JNI Weak Roots";
 163   _phase_names[scan_synchronizer_roots]         = "    S: Synchronizer Roots";
 164   _phase_names[scan_flat_profiler_roots]        = "    S: Flat Profiler Roots";
 165   _phase_names[scan_management_roots]           = "    S: Management Roots";
 166   _phase_names[scan_system_dictionary_roots]    = "    S: System Dict Roots";
 167   _phase_names[scan_cldg_roots]                 = "    S: CLDG Roots";
 168   _phase_names[scan_jvmti_roots]                = "    S: JVMTI Roots";
 169   _phase_names[scan_string_dedup_table_roots]   = "    S: Dedup Table Roots";
 170   _phase_names[scan_string_dedup_queue_roots]   = "    S: Dedup Queue Roots";
 171   _phase_names[scan_finish_queues]              = "    S: Finish Queues";
 172 
 173   _phase_names[update_roots]                    = "  Update Roots";
 174   _phase_names[update_thread_roots]             = "    U: Thread Roots";
 175   _phase_names[update_code_roots]               = "    U: Code Cache Roots";
 176   _phase_names[update_string_table_roots]       = "    U: String Table Roots";
 177   _phase_names[update_universe_roots]           = "    U: Universe Roots";
 178   _phase_names[update_jni_roots]                = "    U: JNI Roots";
 179   _phase_names[update_jni_weak_roots]           = "    U: JNI Weak Roots";
 180   _phase_names[update_synchronizer_roots]       = "    U: Synchronizer Roots";
 181   _phase_names[update_flat_profiler_roots]      = "    U: Flat Profiler Roots";
 182   _phase_names[update_management_roots]         = "    U: Management Roots";
 183   _phase_names[update_system_dictionary_roots]  = "    U: System Dict Roots";
 184   _phase_names[update_cldg_roots]               = "    U: CLDG Roots";
 185   _phase_names[update_jvmti_roots]              = "    U: JVMTI Roots";
 186   _phase_names[update_string_dedup_table_roots] = "    U: Dedup Table Roots";
 187   _phase_names[update_string_dedup_queue_roots] = "    U: Dedup Queue Roots";
 188   _phase_names[update_finish_queues]            = "    U: Finish Queues";
 189 
 190   _phase_names[init_evac]                       = "  Initial Evacuation";
 191   _phase_names[evac_thread_roots]               = "    E: Thread Roots";
 192   _phase_names[evac_code_roots]                 = "    E: Code Cache Roots";
 193   _phase_names[evac_string_table_roots]         = "    E: String Table Roots";
 194   _phase_names[evac_universe_roots]             = "    E: Universe Roots";
 195   _phase_names[evac_jni_roots]                  = "    E: JNI Roots";
 196   _phase_names[evac_jni_weak_roots]             = "    E: JNI Weak Roots";
 197   _phase_names[evac_synchronizer_roots]         = "    E: Synchronizer Roots";
 198   _phase_names[evac_flat_profiler_roots]        = "    E: Flat Profiler Roots";
 199   _phase_names[evac_management_roots]           = "    E: Management Roots";
 200   _phase_names[evac_system_dictionary_roots]    = "    E: System Dict Roots";
 201   _phase_names[evac_cldg_roots]                 = "    E: CLDG Roots";
 202   _phase_names[evac_jvmti_roots]                = "    E: JVMTI Roots";
 203   _phase_names[evac_string_dedup_table_roots]   = "    E: String Dedup Table Roots";
 204   _phase_names[evac_string_dedup_queue_roots]   = "    E: String Dedup Queue Roots";
 205   _phase_names[evac_finish_queues]              = "    E: Finish Queues";
 206 
 207   _phase_names[recycle_regions]                 = "  Recycle regions";
 208 
 209   _phase_names[degen_gc_gross]                  = "Pause Degenerated GC (G)";
 210   _phase_names[degen_gc]                        = "Pause Degenerated GC (N)";
 211   _phase_names[degen_gc_update_roots]           = "  Degenerated GC update roots";
 212 
 213   _phase_names[full_gc_gross]                   = "Pause Full GC (G)";
 214   _phase_names[full_gc]                         = "Pause Full GC (N)";
 215   _phase_names[full_gc_heapdumps]               = "  Heap Dumps";
 216   _phase_names[full_gc_prepare]                 = "  Prepare";
 217   _phase_names[full_gc_roots]                   = "  Roots";
 218   _phase_names[full_gc_thread_roots]            = "    F: Thread Roots";
 219   _phase_names[full_gc_code_roots]              = "    F: Code Cache Roots";
 220   _phase_names[full_gc_string_table_roots]      = "    F: String Table Roots";
 221   _phase_names[full_gc_universe_roots]          = "    F: Universe Roots";
 222   _phase_names[full_gc_jni_roots]               = "    F: JNI Roots";
 223   _phase_names[full_gc_jni_weak_roots]          = "    F: JNI Weak Roots";
 224   _phase_names[full_gc_synchronizer_roots]      = "    F: Synchronizer Roots";
 225   _phase_names[full_gc_flat_profiler_roots]     = "    F: Flat Profiler Roots";
 226   _phase_names[full_gc_management_roots]        = "    F: Management Roots";
 227   _phase_names[full_gc_system_dictionary_roots] = "    F: System Dict Roots";
 228   _phase_names[full_gc_cldg_roots]              = "    F: CLDG Roots";
 229   _phase_names[full_gc_jvmti_roots]             = "    F: JVMTI Roots";
 230   _phase_names[full_gc_string_dedup_table_roots]
 231                                                 = "    F: Dedup Table Roots";
 232   _phase_names[full_gc_string_dedup_queue_roots]
 233                                                 = "    F: Dedup Queue Roots";
 234   _phase_names[full_gc_finish_queues]           = "    F: Finish Queues";
 235   _phase_names[full_gc_mark]                    = "  Mark";
 236   _phase_names[full_gc_mark_finish_queues]      = "    Finish Queues";
 237   _phase_names[full_gc_mark_termination]        = "      Termination";
 238   _phase_names[full_gc_weakrefs]                = "    Weak References";
 239   _phase_names[full_gc_weakrefs_process]        = "      Process";
 240   _phase_names[full_gc_weakrefs_termination]    = "        Termination";
 241   _phase_names[full_gc_purge]                   = "    System Purge";
 242   _phase_names[full_gc_purge_class_unload]      = "      Unload Classes";
 243   _phase_names[full_gc_purge_par]               = "    Parallel Cleanup";
 244   _phase_names[full_gc_purge_par_codecache]     = "      Code Cache";
 245   _phase_names[full_gc_purge_par_symbstring]    = "      String/Symbol Tables";
 246   _phase_names[full_gc_purge_par_classes]       = "      Clean Classes";
 247   _phase_names[full_gc_purge_par_sync]          = "      Synchronization";
 248   _phase_names[full_gc_purge_cldg]              = "    CLDG";
 249   _phase_names[full_gc_purge_string_dedup]
 250                                                 = "    String Dedup";
 251   _phase_names[full_gc_calculate_addresses]     = "  Calculate Addresses";
 252   _phase_names[full_gc_calculate_addresses_regular] = "    Regular Objects";
 253   _phase_names[full_gc_calculate_addresses_humong]  = "    Humongous Objects";
 254   _phase_names[full_gc_adjust_pointers]         = "  Adjust Pointers";
 255   _phase_names[full_gc_copy_objects]            = "  Copy Objects";
 256   _phase_names[full_gc_copy_objects_regular]    = "    Regular Objects";
 257   _phase_names[full_gc_copy_objects_humong]     = "    Humongous Objects";
 258   _phase_names[full_gc_copy_objects_reset_next]     = "    Reset Next Bitmap";
 259   _phase_names[full_gc_copy_objects_reset_complete] = "    Reset Complete Bitmap";
 260   _phase_names[full_gc_copy_objects_rebuild]     = "    Rebuild Region Sets";
 261   _phase_names[full_gc_resize_tlabs]            = "  Resize TLABs";
 262 
 263   _phase_names[init_traversal_gc_gross]           = "Pause Init Traversal (G)";
 264   _phase_names[init_traversal_gc]                 = "Pause Init Traversal (N)";
 265   _phase_names[traversal_gc_prepare]              = "  Prepare";
 266   _phase_names[traversal_gc_accumulate_stats]     = "    Accumulate Stats";
 267   _phase_names[traversal_gc_make_parsable]        = "    Make Parsable";
 268   _phase_names[traversal_gc_resize_tlabs]         = "    Resize TLABs";
 269   _phase_names[init_traversal_gc_work]            = "  Work";
 270   _phase_names[init_traversal_gc_thread_roots]        = "    TI: Thread Roots";
 271   _phase_names[init_traversal_gc_code_roots]          = "    TI: Code Cache Roots";
 272   _phase_names[init_traversal_gc_string_table_roots]  = "    TI: String Table Roots";
 273   _phase_names[init_traversal_gc_universe_roots]      = "    TI: Universe Roots";
 274   _phase_names[init_traversal_gc_jni_roots]           = "    TI: JNI Roots";
 275   _phase_names[init_traversal_gc_jni_weak_roots]      = "    TI: JNI Weak Roots";
 276   _phase_names[init_traversal_gc_synchronizer_roots]  = "    TI: Synchronizer Roots";
 277   _phase_names[init_traversal_gc_flat_profiler_roots] = "    TI: Flat Profiler Roots";
 278   _phase_names[init_traversal_gc_management_roots]    = "    TI: Management Roots";
 279   _phase_names[init_traversal_gc_system_dict_roots]   = "    TI: System Dict Roots";
 280   _phase_names[init_traversal_gc_cldg_roots]          = "    TI: CLDG Roots";
 281   _phase_names[init_traversal_gc_jvmti_roots]         = "    TI: JVMTI Roots";
 282   _phase_names[init_traversal_gc_string_dedup_table_roots]
 283                                                       = "    TI: Dedup Table Roots";
 284   _phase_names[init_traversal_gc_string_dedup_queue_roots]
 285                                                       = "    TI: Dedup Queue Roots";
 286   _phase_names[init_traversal_gc_finish_queues]       = "    TI: Finish Queues";
 287   _phase_names[final_traversal_gc_gross]          = "Pause Final Traversal (G)";
 288   _phase_names[final_traversal_gc]                = "Pause Final Traversal (N)";
 289   _phase_names[final_traversal_gc_work]           = "  Work";
 290   _phase_names[final_traversal_gc_thread_roots]        = "    TF: Thread Roots";
 291   _phase_names[final_traversal_gc_code_roots]          = "    TF: Code Cache Roots";
 292   _phase_names[final_traversal_gc_string_table_roots]  = "    TF: String Table Roots";
 293   _phase_names[final_traversal_gc_universe_roots]      = "    TF: Universe Roots";
 294   _phase_names[final_traversal_gc_jni_roots]           = "    TF: JNI Roots";
 295   _phase_names[final_traversal_gc_jni_weak_roots]      = "    TF: JNI Weak Roots";
 296   _phase_names[final_traversal_gc_synchronizer_roots]  = "    TF: Synchronizer Roots";
 297   _phase_names[final_traversal_gc_flat_profiler_roots] = "    TF: Flat Profiler Roots";
 298   _phase_names[final_traversal_gc_management_roots]    = "    TF: Management Roots";
 299   _phase_names[final_traversal_gc_system_dict_roots]   = "    TF: System Dict Roots";
 300   _phase_names[final_traversal_gc_cldg_roots]          = "    TF: CLDG Roots";
 301   _phase_names[final_traversal_gc_jvmti_roots]         = "    TF: JVMTI Roots";
 302   _phase_names[final_traversal_gc_string_dedup_table_roots]
 303                                                        = "    TF: Dedup Table Roots";
 304   _phase_names[final_traversal_gc_string_dedup_queue_roots]
 305                                                        = "    TF: Dedup Queue Roots";
 306   _phase_names[final_traversal_gc_finish_queues]       = "    TF: Finish Queues";
 307   _phase_names[final_traversal_gc_termination]         = "    TF:   Termination";
 308   _phase_names[final_traversal_update_roots]           = "  Update Roots";
 309   _phase_names[final_traversal_update_thread_roots]        = "    TU: Thread Roots";
 310   _phase_names[final_traversal_update_code_roots]          = "    TU: Code Cache Roots";
 311   _phase_names[final_traversal_update_string_table_roots]  = "    TU: String Table Roots";
 312   _phase_names[final_traversal_update_universe_roots]      = "    TU: Universe Roots";
 313   _phase_names[final_traversal_update_jni_roots]           = "    TU: JNI Roots";
 314   _phase_names[final_traversal_update_jni_weak_roots]      = "    TU: JNI Weak Roots";
 315   _phase_names[final_traversal_update_synchronizer_roots]  = "    TU: Synchronizer Roots";
 316   _phase_names[final_traversal_update_flat_profiler_roots] = "    TU: Flat Profiler Roots";
 317   _phase_names[final_traversal_update_management_roots]    = "    TU: Management Roots";
 318   _phase_names[final_traversal_update_system_dict_roots]   = "    TU: System Dict Roots";
 319   _phase_names[final_traversal_update_cldg_roots]          = "    TU: CLDG Roots";
 320   _phase_names[final_traversal_update_jvmti_roots]         = "    TU: JVMTI Roots";
 321   _phase_names[final_traversal_update_string_dedup_table_roots]
 322                                                            = "    TU: Dedup Table Roots";
 323   _phase_names[final_traversal_update_string_dedup_queue_roots]
 324                                                            = "    TU: Dedup Queue Roots";
 325   _phase_names[final_traversal_update_finish_queues]       = "    TU: Finish Queues";
 326 
 327   _phase_names[traversal_gc_cleanup]              = "  Cleanup";
 328 
 329   _phase_names[pause_other]                     = "Pause Other";
 330 
 331   _phase_names[conc_mark]                       = "Concurrent Marking";
 332   _phase_names[conc_termination]                = "  Termination";
 333   _phase_names[conc_preclean]                   = "Concurrent Precleaning";
 334   _phase_names[conc_evac]                       = "Concurrent Evacuation";
 335   _phase_names[conc_cleanup]                    = "Concurrent Cleanup";
 336   _phase_names[conc_cleanup_recycle]            = "  Recycle";
 337   _phase_names[conc_cleanup_reset_bitmaps]      = "  Reset Bitmaps";
 338   _phase_names[conc_other]                      = "Concurrent Other";
 339   _phase_names[conc_traversal]                  = "Concurrent Traversal";
 340   _phase_names[conc_traversal_termination]      = "  Termination";
 341 
 342   _phase_names[conc_uncommit]                   = "Concurrent Uncommit";
 343 
 344   _phase_names[init_update_refs_gross]          = "Pause Init  Update Refs (G)";
 345   _phase_names[init_update_refs]                = "Pause Init  Update Refs (N)";
 346   _phase_names[conc_update_refs]                = "Concurrent Update Refs";
 347   _phase_names[final_update_refs_gross]         = "Pause Final Update Refs (G)";
 348   _phase_names[final_update_refs]               = "Pause Final Update Refs (N)";
 349 
 350   _phase_names[final_update_refs_finish_work]          = "  Finish Work";
 351   _phase_names[final_update_refs_roots]                = "  Update Roots";
 352   _phase_names[final_update_refs_thread_roots]         = "    UR: Thread Roots";
 353   _phase_names[final_update_refs_code_roots]           = "    UR: Code Cache Roots";
 354   _phase_names[final_update_refs_string_table_roots]   = "    UR: String Table Roots";
 355   _phase_names[final_update_refs_universe_roots]       = "    UR: Universe Roots";
 356   _phase_names[final_update_refs_jni_roots]            = "    UR: JNI Roots";
 357   _phase_names[final_update_refs_jni_weak_roots]       = "    UR: JNI Weak Roots";
 358   _phase_names[final_update_refs_synchronizer_roots]   = "    UR: Synchronizer Roots";
 359   _phase_names[final_update_refs_flat_profiler_roots]  = "    UR: Flat Profiler Roots";
 360   _phase_names[final_update_refs_management_roots]     = "    UR: Management Roots";
 361   _phase_names[final_update_refs_system_dict_roots]    = "    UR: System Dict Roots";
 362   _phase_names[final_update_refs_cldg_roots]           = "    UR: CLDG Roots";
 363   _phase_names[final_update_refs_jvmti_roots]          = "    UR: JVMTI Roots";
 364   _phase_names[final_update_refs_string_dedup_table_roots]
 365                                                        = "    UR: Dedup Table Roots";
 366   _phase_names[final_update_refs_string_dedup_queue_roots]
 367                                                        = "    UR: Dedup Queue Roots";
 368   _phase_names[final_update_refs_finish_queues]        = "    UR: Finish Queues";
 369   _phase_names[final_update_refs_recycle]              = "  Recycle";
 370 }
 371 
 372 ShenandoahWorkerTimings::ShenandoahWorkerTimings(uint max_gc_threads) :
 373         _max_gc_threads(max_gc_threads)
 374 {
 375   assert(max_gc_threads > 0, "Must have some GC threads");
 376 
 377   // Root scanning phases
 378   _gc_par_phases[ShenandoahPhaseTimings::ThreadRoots]             = new WorkerDataArray<double>(max_gc_threads, "Thread Roots (ms):");
 379   _gc_par_phases[ShenandoahPhaseTimings::CodeCacheRoots]          = new WorkerDataArray<double>(max_gc_threads, "CodeCache Roots (ms):");
 380   _gc_par_phases[ShenandoahPhaseTimings::StringTableRoots]        = new WorkerDataArray<double>(max_gc_threads, "StringTable Roots (ms):");
 381   _gc_par_phases[ShenandoahPhaseTimings::UniverseRoots]           = new WorkerDataArray<double>(max_gc_threads, "Universe Roots (ms):");
 382   _gc_par_phases[ShenandoahPhaseTimings::JNIRoots]                = new WorkerDataArray<double>(max_gc_threads, "JNI Handles Roots (ms):");
 383   _gc_par_phases[ShenandoahPhaseTimings::JNIWeakRoots]            = new WorkerDataArray<double>(max_gc_threads, "JNI Weak Roots (ms):");
 384   _gc_par_phases[ShenandoahPhaseTimings::ObjectSynchronizerRoots] = new WorkerDataArray<double>(max_gc_threads, "ObjectSynchronizer Roots (ms):");
 385   _gc_par_phases[ShenandoahPhaseTimings::FlatProfilerRoots]       = new WorkerDataArray<double>(max_gc_threads, "FlatProfiler Roots (ms):");
 386   _gc_par_phases[ShenandoahPhaseTimings::ManagementRoots]         = new WorkerDataArray<double>(max_gc_threads, "Management Roots (ms):");
 387   _gc_par_phases[ShenandoahPhaseTimings::SystemDictionaryRoots]   = new WorkerDataArray<double>(max_gc_threads, "SystemDictionary Roots (ms):");
 388   _gc_par_phases[ShenandoahPhaseTimings::CLDGRoots]               = new WorkerDataArray<double>(max_gc_threads, "CLDG Roots (ms):");
 389   _gc_par_phases[ShenandoahPhaseTimings::JVMTIRoots]              = new WorkerDataArray<double>(max_gc_threads, "JVMTI Roots (ms):");
 390   _gc_par_phases[ShenandoahPhaseTimings::StringDedupTableRoots]   = new WorkerDataArray<double>(max_gc_threads, "String Dedup Table Roots (ms):");
 391   _gc_par_phases[ShenandoahPhaseTimings::StringDedupQueueRoots]   = new WorkerDataArray<double>(max_gc_threads, "String Dedup Queue Roots (ms):");
 392   _gc_par_phases[ShenandoahPhaseTimings::FinishQueues]            = new WorkerDataArray<double>(max_gc_threads, "Finish Queues (ms):");
 393 }
 394 
 395 // record the time a phase took in seconds
 396 void ShenandoahWorkerTimings::record_time_secs(ShenandoahPhaseTimings::GCParPhases phase, uint worker_i, double secs) {
 397   _gc_par_phases[phase]->set(worker_i, secs);
 398 }
 399 
 400 double ShenandoahWorkerTimings::average(uint i) const {
 401   return _gc_par_phases[i]->average();
 402 }
 403 
 404 void ShenandoahWorkerTimings::reset(uint i) {
 405   _gc_par_phases[i]->reset();
 406 }
 407 
 408 void ShenandoahWorkerTimings::print() const {
 409   for (uint i = 0; i < ShenandoahPhaseTimings::GCParPhasesSentinel; i++) {
 410     _gc_par_phases[i]->print_summary_on(tty);
 411   }
 412 }
 413 
 414 ShenandoahWorkerTimingsTracker::ShenandoahWorkerTimingsTracker(ShenandoahWorkerTimings* worker_times,
 415                                                                ShenandoahPhaseTimings::GCParPhases phase, uint worker_id) :
 416         _phase(phase), _worker_times(worker_times), _worker_id(worker_id) {
 417   if (_worker_times != NULL) {
 418     _start_time = os::elapsedTime();
 419   }
 420 }
 421 
 422 ShenandoahWorkerTimingsTracker::~ShenandoahWorkerTimingsTracker() {
 423   if (_worker_times != NULL) {
 424     _worker_times->record_time_secs(_phase, _worker_id, os::elapsedTime() - _start_time);
 425   }
 426 }
 427 
 428 ShenandoahTerminationTimings::ShenandoahTerminationTimings(uint max_gc_threads) {
 429   _gc_termination_phase = new WorkerDataArray<double>(max_gc_threads, "Task Termination (ms):");
 430 }
 431 
 432 void ShenandoahTerminationTimings::record_time_secs(uint worker_id, double secs) {
 433   if (_gc_termination_phase->get(worker_id) == WorkerDataArray<double>::uninitialized()) {
 434     _gc_termination_phase->set(worker_id, secs);
 435   } else {
 436     // worker may re-enter termination phase
 437     _gc_termination_phase->add(worker_id, secs);
 438   }
 439 }
 440 
 441 void ShenandoahTerminationTimings::print() const {
 442   _gc_termination_phase->print_summary_on(tty);
 443 }
 444 
 445 ShenandoahTerminationTimingsTracker::ShenandoahTerminationTimingsTracker(uint worker_id) :
 446   _worker_id(worker_id)  {
 447   if (ShenandoahTerminationTrace) {
 448     _start_time = os::elapsedTime();
 449   }
 450 }
 451 
 452 ShenandoahTerminationTimingsTracker::~ShenandoahTerminationTimingsTracker() {
 453   if (ShenandoahTerminationTrace) {
 454     ShenandoahHeap::heap()->phase_timings()->termination_times()->record_time_secs(_worker_id, os::elapsedTime() - _start_time);
 455   }
 456 }
 457 
 458 ShenandoahPhaseTimings::Phase ShenandoahTerminationTracker::currentPhase = ShenandoahPhaseTimings::_num_phases;
 459 
 460 ShenandoahTerminationTracker::ShenandoahTerminationTracker(ShenandoahPhaseTimings::Phase phase) : _phase(phase) {
 461   assert(currentPhase == ShenandoahPhaseTimings::_num_phases, "Should be invalid");
 462   assert(phase == ShenandoahPhaseTimings::termination ||
 463          phase == ShenandoahPhaseTimings::final_traversal_gc_termination ||
 464          phase == ShenandoahPhaseTimings::full_gc_mark_termination ||
 465          phase == ShenandoahPhaseTimings::conc_termination ||
 466          phase == ShenandoahPhaseTimings::conc_traversal_termination ||
 467          phase == ShenandoahPhaseTimings::weakrefs_termination ||
 468          phase == ShenandoahPhaseTimings::full_gc_weakrefs_termination,
 469          "Only these phases");
 470 
 471   assert(Thread::current()->is_VM_thread() || Thread::current()->is_ConcurrentGC_thread(),
 472     "Called from wrong thread");
 473 
 474   currentPhase = phase;
 475   ShenandoahHeap::heap()->phase_timings()->termination_times()->reset();
 476 }
 477 
 478 ShenandoahTerminationTracker::~ShenandoahTerminationTracker() {
 479   assert(_phase == currentPhase, "Can not change phase");
 480   ShenandoahPhaseTimings* phase_times = ShenandoahHeap::heap()->phase_timings();
 481 
 482   double t = phase_times->termination_times()->average();
 483   phase_times->record_phase_time(_phase, t * 1000 * 1000);
 484   debug_only(currentPhase = ShenandoahPhaseTimings::_num_phases;)
 485 }