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 }