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 }