1 /* 2 * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "gc/g1/g1CollectedHeap.inline.hpp" 27 #include "gc/g1/g1GCParPhaseTimesTracker.hpp" 28 #include "gc/g1/g1GCPhaseTimes.hpp" 29 #include "gc/g1/g1HotCardCache.hpp" 30 #include "gc/g1/g1ParScanThreadState.inline.hpp" 31 #include "gc/g1/g1StringDedup.hpp" 32 #include "gc/shared/gcTimer.hpp" 33 #include "gc/shared/workerDataArray.inline.hpp" 34 #include "memory/resourceArea.hpp" 35 #include "logging/log.hpp" 36 #include "logging/logStream.hpp" 37 #include "runtime/timer.hpp" 38 #include "runtime/os.hpp" 39 #include "utilities/macros.hpp" 40 41 static const char* indent(uint level) { 42 static const char* Indents[] = {"", " ", " ", " ", " ", " "}; 43 assert(level < ARRAY_SIZE(Indents), "Too high indent level %u", level); 44 return Indents[level]; 45 } 46 47 G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) : 48 _max_gc_threads(max_gc_threads), 49 _gc_start_counter(0), 50 _gc_pause_time_ms(0.0), 51 _ref_phase_times(gc_timer, max_gc_threads), 52 _weak_phase_times(max_gc_threads) 53 { 54 assert(max_gc_threads > 0, "Must have some GC threads"); 55 56 _gc_par_phases[GCWorkerStart] = new WorkerDataArray<double>("GC Worker Start (ms):", max_gc_threads); 57 _gc_par_phases[ExtRootScan] = new WorkerDataArray<double>("Ext Root Scanning (ms):", max_gc_threads); 58 59 // Root scanning phases 60 _gc_par_phases[ThreadRoots] = new WorkerDataArray<double>("Thread Roots (ms):", max_gc_threads); 61 _gc_par_phases[UniverseRoots] = new WorkerDataArray<double>("Universe Roots (ms):", max_gc_threads); 62 _gc_par_phases[JNIRoots] = new WorkerDataArray<double>("JNI Handles Roots (ms):", max_gc_threads); 63 _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray<double>("ObjectSynchronizer Roots (ms):", max_gc_threads); 64 _gc_par_phases[ManagementRoots] = new WorkerDataArray<double>("Management Roots (ms):", max_gc_threads); 65 _gc_par_phases[VMGlobalRoots] = new WorkerDataArray<double>("VM Global Roots (ms):", max_gc_threads); 66 _gc_par_phases[CLDGRoots] = new WorkerDataArray<double>("CLDG Roots (ms):", max_gc_threads); 67 _gc_par_phases[JVMTIRoots] = new WorkerDataArray<double>("JVMTI Roots (ms):", max_gc_threads); 68 AOT_ONLY(_gc_par_phases[AOTCodeRoots] = new WorkerDataArray<double>("AOT Root Scan (ms):", max_gc_threads);) 69 _gc_par_phases[CMRefRoots] = new WorkerDataArray<double>("CM RefProcessor Roots (ms):", max_gc_threads); 70 71 _gc_par_phases[MergeER] = new WorkerDataArray<double>("Eager Reclaim (ms):", max_gc_threads); 72 73 _gc_par_phases[MergeRS] = new WorkerDataArray<double>("Remembered Sets (ms):", max_gc_threads); 74 _gc_par_phases[MergeRS]->create_thread_work_items("Merged Sparse:", MergeRSMergedSparse); 75 _gc_par_phases[MergeRS]->create_thread_work_items("Merged Fine:", MergeRSMergedFine); 76 _gc_par_phases[MergeRS]->create_thread_work_items("Merged Coarse:", MergeRSMergedCoarse); 77 _gc_par_phases[MergeRS]->create_thread_work_items("Dirty Cards:", MergeRSDirtyCards); 78 79 _gc_par_phases[OptMergeRS] = new WorkerDataArray<double>("Optional Remembered Sets (ms):", max_gc_threads); 80 _gc_par_phases[OptMergeRS]->create_thread_work_items("Merged Sparse:", MergeRSMergedSparse); 81 _gc_par_phases[OptMergeRS]->create_thread_work_items("Merged Fine:", MergeRSMergedFine); 82 _gc_par_phases[OptMergeRS]->create_thread_work_items("Merged Coarse:", MergeRSMergedCoarse); 83 _gc_par_phases[OptMergeRS]->create_thread_work_items("Dirty Cards:", MergeRSDirtyCards); 84 85 _gc_par_phases[MergeLB] = new WorkerDataArray<double>("Log Buffers (ms):", max_gc_threads); 86 if (G1HotCardCache::default_use_cache()) { 87 _gc_par_phases[MergeHCC] = new WorkerDataArray<double>("Hot Card Cache (ms):", max_gc_threads); 88 _gc_par_phases[MergeHCC]->create_thread_work_items("Dirty Cards:", MergeHCCDirtyCards); 89 _gc_par_phases[MergeHCC]->create_thread_work_items("Skipped Cards:", MergeHCCSkippedCards); 90 } else { 91 _gc_par_phases[MergeHCC] = NULL; 92 } 93 _gc_par_phases[ScanHR] = new WorkerDataArray<double>("Scan Heap Roots (ms):", max_gc_threads); 94 _gc_par_phases[OptScanHR] = new WorkerDataArray<double>("Optional Scan Heap Roots (ms):", max_gc_threads); 95 _gc_par_phases[CodeRoots] = new WorkerDataArray<double>("Code Root Scan (ms):", max_gc_threads); 96 _gc_par_phases[OptCodeRoots] = new WorkerDataArray<double>("Optional Code Root Scan (ms):", max_gc_threads); 97 _gc_par_phases[ObjCopy] = new WorkerDataArray<double>("Object Copy (ms):", max_gc_threads); 98 _gc_par_phases[OptObjCopy] = new WorkerDataArray<double>("Optional Object Copy (ms):", max_gc_threads); 99 _gc_par_phases[Termination] = new WorkerDataArray<double>("Termination (ms):", max_gc_threads); 100 _gc_par_phases[OptTermination] = new WorkerDataArray<double>("Optional Termination (ms):", max_gc_threads); 101 _gc_par_phases[GCWorkerTotal] = new WorkerDataArray<double>("GC Worker Total (ms):", max_gc_threads); 102 _gc_par_phases[GCWorkerEnd] = new WorkerDataArray<double>("GC Worker End (ms):", max_gc_threads); 103 _gc_par_phases[Other] = new WorkerDataArray<double>("GC Worker Other (ms):", max_gc_threads); 104 105 _gc_par_phases[ScanHR]->create_thread_work_items("Scanned Cards:", ScanHRScannedCards); 106 _gc_par_phases[ScanHR]->create_thread_work_items("Scanned Blocks:", ScanHRScannedBlocks); 107 _gc_par_phases[ScanHR]->create_thread_work_items("Claimed Chunks:", ScanHRClaimedChunks); 108 109 _gc_par_phases[OptScanHR]->create_thread_work_items("Scanned Cards:", ScanHRScannedCards); 110 _gc_par_phases[OptScanHR]->create_thread_work_items("Scanned Blocks:", ScanHRScannedBlocks); 111 _gc_par_phases[OptScanHR]->create_thread_work_items("Claimed Chunks:", ScanHRClaimedChunks); 112 _gc_par_phases[OptScanHR]->create_thread_work_items("Scanned Refs:", ScanHRScannedOptRefs); 113 _gc_par_phases[OptScanHR]->create_thread_work_items("Used Memory:", ScanHRUsedMemory); 114 115 _gc_par_phases[MergeLB]->create_thread_work_items("Dirty Cards:", MergeLBDirtyCards); 116 _gc_par_phases[MergeLB]->create_thread_work_items("Skipped Cards:", MergeLBSkippedCards); 117 118 _gc_par_phases[MergePSS] = new WorkerDataArray<double>("Merge Per-Thread State", 1 /* length */, true /* is_serial */); 119 120 _gc_par_phases[MergePSS]->create_thread_work_items("Copied Bytes", MergePSSCopiedBytes, max_gc_threads); 121 _gc_par_phases[MergePSS]->create_thread_work_items("LAB Waste", MergePSSLABWasteBytes, max_gc_threads); 122 _gc_par_phases[MergePSS]->create_thread_work_items("LAB Undo Waste", MergePSSLABUndoWasteBytes, max_gc_threads); 123 124 _gc_par_phases[Termination]->create_thread_work_items("Termination Attempts:"); 125 126 _gc_par_phases[OptTermination]->create_thread_work_items("Optional Termination Attempts:"); 127 128 if (UseStringDeduplication) { 129 _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray<double>("Queue Fixup (ms):", max_gc_threads); 130 _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray<double>("Table Fixup (ms):", max_gc_threads); 131 } else { 132 _gc_par_phases[StringDedupQueueFixup] = NULL; 133 _gc_par_phases[StringDedupTableFixup] = NULL; 134 } 135 136 _gc_par_phases[RedirtyCards] = new WorkerDataArray<double>("Parallel Redirty (ms):", max_gc_threads); 137 _gc_par_phases[RedirtyCards]->create_thread_work_items("Redirtied Cards:"); 138 139 _gc_par_phases[ParFreeCSet] = new WorkerDataArray<double>("Parallel Free Collection Set (ms):", max_gc_threads); 140 _gc_par_phases[YoungFreeCSet] = new WorkerDataArray<double>("Young Free Collection Set (ms):", max_gc_threads); 141 _gc_par_phases[NonYoungFreeCSet] = new WorkerDataArray<double>("Non-Young Free Collection Set (ms):", max_gc_threads); 142 _gc_par_phases[RebuildFreeList] = new WorkerDataArray<double>("Parallel Rebuild Free List (ms):", max_gc_threads); 143 144 reset(); 145 } 146 147 void G1GCPhaseTimes::reset() { 148 _cur_collection_initial_evac_time_ms = 0.0; 149 _cur_optional_evac_time_ms = 0.0; 150 _cur_collection_code_root_fixup_time_ms = 0.0; 151 _cur_strong_code_root_purge_time_ms = 0.0; 152 _cur_merge_heap_roots_time_ms = 0.0; 153 _cur_optional_merge_heap_roots_time_ms = 0.0; 154 _cur_prepare_merge_heap_roots_time_ms = 0.0; 155 _cur_optional_prepare_merge_heap_roots_time_ms = 0.0; 156 _cur_evac_fail_recalc_used = 0.0; 157 _cur_evac_fail_remove_self_forwards = 0.0; 158 _cur_string_deduplication_time_ms = 0.0; 159 _cur_prepare_tlab_time_ms = 0.0; 160 _cur_resize_tlab_time_ms = 0.0; 161 _cur_concatenate_dirty_card_logs_time_ms = 0.0; 162 _cur_derived_pointer_table_update_time_ms = 0.0; 163 _cur_clear_ct_time_ms = 0.0; 164 _cur_expand_heap_time_ms = 0.0; 165 _cur_ref_proc_time_ms = 0.0; 166 _cur_collection_start_sec = 0.0; 167 _root_region_scan_wait_time_ms = 0.0; 168 _external_accounted_time_ms = 0.0; 169 _recorded_prepare_heap_roots_time_ms = 0.0; 170 _recorded_clear_claimed_marks_time_ms = 0.0; 171 _recorded_young_cset_choice_time_ms = 0.0; 172 _recorded_non_young_cset_choice_time_ms = 0.0; 173 _recorded_redirty_logged_cards_time_ms = 0.0; 174 _recorded_preserve_cm_referents_time_ms = 0.0; 175 _recorded_start_new_cset_time_ms = 0.0; 176 _recorded_total_free_cset_time_ms = 0.0; 177 _recorded_serial_free_cset_time_ms = 0.0; 178 _recorded_total_rebuild_freelist_time_ms = 0.0; 179 _recorded_serial_rebuild_freelist_time_ms = 0.0; 180 _cur_fast_reclaim_humongous_time_ms = 0.0; 181 _cur_region_register_time = 0.0; 182 _cur_fast_reclaim_humongous_total = 0; 183 _cur_fast_reclaim_humongous_candidates = 0; 184 _cur_fast_reclaim_humongous_reclaimed = 0; 185 _cur_verify_before_time_ms = 0.0; 186 _cur_verify_after_time_ms = 0.0; 187 188 for (int i = 0; i < GCParPhasesSentinel; i++) { 189 if (_gc_par_phases[i] != NULL) { 190 _gc_par_phases[i]->reset(); 191 } 192 } 193 194 _ref_phase_times.reset(); 195 _weak_phase_times.reset(); 196 } 197 198 void G1GCPhaseTimes::note_gc_start() { 199 _gc_start_counter = os::elapsed_counter(); 200 reset(); 201 } 202 203 #define ASSERT_PHASE_UNINITIALIZED(phase) \ 204 assert(_gc_par_phases[phase] == NULL || _gc_par_phases[phase]->get(i) == uninitialized, "Phase " #phase " reported for thread that was not started"); 205 206 double G1GCPhaseTimes::worker_time(GCParPhases phase, uint worker) { 207 if (_gc_par_phases[phase] == NULL) { 208 return 0.0; 209 } 210 double value = _gc_par_phases[phase]->get(worker); 211 if (value != WorkerDataArray<double>::uninitialized()) { 212 return value; 213 } 214 return 0.0; 215 } 216 217 void G1GCPhaseTimes::note_gc_end() { 218 _gc_pause_time_ms = TimeHelper::counter_to_millis(os::elapsed_counter() - _gc_start_counter); 219 220 double uninitialized = WorkerDataArray<double>::uninitialized(); 221 222 for (uint i = 0; i < _max_gc_threads; i++) { 223 double worker_start = _gc_par_phases[GCWorkerStart]->get(i); 224 if (worker_start != uninitialized) { 225 assert(_gc_par_phases[GCWorkerEnd]->get(i) != uninitialized, "Worker started but not ended."); 226 double total_worker_time = _gc_par_phases[GCWorkerEnd]->get(i) - _gc_par_phases[GCWorkerStart]->get(i); 227 record_time_secs(GCWorkerTotal, i , total_worker_time); 228 229 double worker_known_time = worker_time(ExtRootScan, i) + 230 worker_time(ScanHR, i) + 231 worker_time(CodeRoots, i) + 232 worker_time(ObjCopy, i) + 233 worker_time(Termination, i); 234 235 record_time_secs(Other, i, total_worker_time - worker_known_time); 236 } else { 237 // Make sure all slots are uninitialized since this thread did not seem to have been started 238 ASSERT_PHASE_UNINITIALIZED(GCWorkerEnd); 239 ASSERT_PHASE_UNINITIALIZED(ExtRootScan); 240 ASSERT_PHASE_UNINITIALIZED(MergeER); 241 ASSERT_PHASE_UNINITIALIZED(MergeRS); 242 ASSERT_PHASE_UNINITIALIZED(OptMergeRS); 243 ASSERT_PHASE_UNINITIALIZED(MergeHCC); 244 ASSERT_PHASE_UNINITIALIZED(MergeLB); 245 ASSERT_PHASE_UNINITIALIZED(ScanHR); 246 ASSERT_PHASE_UNINITIALIZED(CodeRoots); 247 ASSERT_PHASE_UNINITIALIZED(OptCodeRoots); 248 ASSERT_PHASE_UNINITIALIZED(ObjCopy); 249 ASSERT_PHASE_UNINITIALIZED(OptObjCopy); 250 ASSERT_PHASE_UNINITIALIZED(Termination); 251 } 252 } 253 } 254 255 #undef ASSERT_PHASE_UNINITIALIZED 256 257 // record the time a phase took in seconds 258 void G1GCPhaseTimes::record_time_secs(GCParPhases phase, uint worker_id, double secs) { 259 _gc_par_phases[phase]->set(worker_id, secs); 260 } 261 262 // add a number of seconds to a phase 263 void G1GCPhaseTimes::add_time_secs(GCParPhases phase, uint worker_id, double secs) { 264 _gc_par_phases[phase]->add(worker_id, secs); 265 } 266 267 void G1GCPhaseTimes::record_or_add_time_secs(GCParPhases phase, uint worker_id, double secs) { 268 if (_gc_par_phases[phase]->get(worker_id) == _gc_par_phases[phase]->uninitialized()) { 269 record_time_secs(phase, worker_id, secs); 270 } else { 271 add_time_secs(phase, worker_id, secs); 272 } 273 } 274 275 double G1GCPhaseTimes::get_time_secs(GCParPhases phase, uint worker_id) { 276 return _gc_par_phases[phase]->get(worker_id); 277 } 278 279 void G1GCPhaseTimes::record_thread_work_item(GCParPhases phase, uint worker_id, size_t count, uint index) { 280 _gc_par_phases[phase]->set_thread_work_item(worker_id, count, index); 281 } 282 283 void G1GCPhaseTimes::record_or_add_thread_work_item(GCParPhases phase, uint worker_id, size_t count, uint index) { 284 _gc_par_phases[phase]->set_or_add_thread_work_item(worker_id, count, index); 285 } 286 287 size_t G1GCPhaseTimes::get_thread_work_item(GCParPhases phase, uint worker_id, uint index) { 288 return _gc_par_phases[phase]->get_thread_work_item(worker_id, index); 289 } 290 291 // return the average time for a phase in milliseconds 292 double G1GCPhaseTimes::average_time_ms(GCParPhases phase) { 293 if (_gc_par_phases[phase] == NULL) { 294 return 0.0; 295 } 296 return _gc_par_phases[phase]->average() * 1000.0; 297 } 298 299 size_t G1GCPhaseTimes::sum_thread_work_items(GCParPhases phase, uint index) { 300 if (_gc_par_phases[phase] == NULL) { 301 return 0; 302 } 303 assert(_gc_par_phases[phase]->thread_work_items(index) != NULL, "No sub count"); 304 return _gc_par_phases[phase]->thread_work_items(index)->sum(); 305 } 306 307 template <class T> 308 void G1GCPhaseTimes::details(T* phase, const char* indent_str) const { 309 LogTarget(Trace, gc, phases, task) lt; 310 if (lt.is_enabled()) { 311 LogStream ls(lt); 312 ls.print("%s", indent_str); 313 phase->print_details_on(&ls); 314 } 315 } 316 317 void G1GCPhaseTimes::log_phase(WorkerDataArray<double>* phase, uint indent_level, outputStream* out, bool print_sum) const { 318 out->print("%s", indent(indent_level)); 319 phase->print_summary_on(out, print_sum); 320 details(phase, indent(indent_level)); 321 322 for (uint i = 0; i < phase->MaxThreadWorkItems; i++) { 323 WorkerDataArray<size_t>* work_items = phase->thread_work_items(i); 324 if (work_items != NULL) { 325 out->print("%s", indent(indent_level + 1)); 326 work_items->print_summary_on(out, true); 327 details(work_items, indent(indent_level + 1)); 328 } 329 } 330 } 331 332 void G1GCPhaseTimes::debug_phase(WorkerDataArray<double>* phase, uint extra_indent) const { 333 LogTarget(Debug, gc, phases) lt; 334 if (lt.is_enabled()) { 335 ResourceMark rm; 336 LogStream ls(lt); 337 log_phase(phase, 2 + extra_indent, &ls, true); 338 } 339 } 340 341 void G1GCPhaseTimes::trace_phase(WorkerDataArray<double>* phase, bool print_sum, uint extra_indent) const { 342 LogTarget(Trace, gc, phases) lt; 343 if (lt.is_enabled()) { 344 LogStream ls(lt); 345 log_phase(phase, 3 + extra_indent, &ls, print_sum); 346 } 347 } 348 349 #define TIME_FORMAT "%.1lfms" 350 351 void G1GCPhaseTimes::info_time(const char* name, double value) const { 352 log_info(gc, phases)("%s%s: " TIME_FORMAT, indent(1), name, value); 353 } 354 355 void G1GCPhaseTimes::debug_time(const char* name, double value) const { 356 log_debug(gc, phases)("%s%s: " TIME_FORMAT, indent(2), name, value); 357 } 358 359 void G1GCPhaseTimes::debug_time_for_reference(const char* name, double value) const { 360 LogTarget(Debug, gc, phases) lt; 361 LogTarget(Debug, gc, phases, ref) lt2; 362 363 if (lt.is_enabled()) { 364 LogStream ls(lt); 365 ls.print_cr("%s%s: " TIME_FORMAT, indent(2), name, value); 366 } else if (lt2.is_enabled()) { 367 LogStream ls(lt2); 368 ls.print_cr("%s%s: " TIME_FORMAT, indent(2), name, value); 369 } 370 } 371 372 void G1GCPhaseTimes::trace_time(const char* name, double value) const { 373 log_trace(gc, phases)("%s%s: " TIME_FORMAT, indent(3), name, value); 374 } 375 376 void G1GCPhaseTimes::trace_count(const char* name, size_t value) const { 377 log_trace(gc, phases)("%s%s: " SIZE_FORMAT, indent(3), name, value); 378 } 379 380 double G1GCPhaseTimes::print_pre_evacuate_collection_set() const { 381 const double sum_ms = _root_region_scan_wait_time_ms + 382 _cur_prepare_tlab_time_ms + 383 _cur_concatenate_dirty_card_logs_time_ms + 384 _recorded_young_cset_choice_time_ms + 385 _recorded_non_young_cset_choice_time_ms + 386 _cur_region_register_time + 387 _recorded_prepare_heap_roots_time_ms + 388 _recorded_clear_claimed_marks_time_ms; 389 390 info_time("Pre Evacuate Collection Set", sum_ms); 391 392 if (_root_region_scan_wait_time_ms > 0.0) { 393 debug_time("Root Region Scan Waiting", _root_region_scan_wait_time_ms); 394 } 395 debug_time("Prepare TLABs", _cur_prepare_tlab_time_ms); 396 debug_time("Concatenate Dirty Card Logs", _cur_concatenate_dirty_card_logs_time_ms); 397 debug_time("Choose Collection Set", (_recorded_young_cset_choice_time_ms + _recorded_non_young_cset_choice_time_ms)); 398 debug_time("Region Register", _cur_region_register_time); 399 if (G1EagerReclaimHumongousObjects) { 400 trace_count("Humongous Total", _cur_fast_reclaim_humongous_total); 401 trace_count("Humongous Candidate", _cur_fast_reclaim_humongous_candidates); 402 } 403 404 debug_time("Prepare Heap Roots", _recorded_prepare_heap_roots_time_ms); 405 if (_recorded_clear_claimed_marks_time_ms > 0.0) { 406 debug_time("Clear Claimed Marks", _recorded_clear_claimed_marks_time_ms); 407 } 408 return sum_ms; 409 } 410 411 double G1GCPhaseTimes::print_evacuate_optional_collection_set() const { 412 const double sum_ms = _cur_optional_evac_time_ms + _cur_optional_merge_heap_roots_time_ms; 413 if (sum_ms > 0) { 414 info_time("Merge Optional Heap Roots", _cur_optional_merge_heap_roots_time_ms); 415 416 debug_time("Prepare Optional Merge Heap Roots", _cur_optional_prepare_merge_heap_roots_time_ms); 417 debug_phase(_gc_par_phases[OptMergeRS]); 418 419 info_time("Evacuate Optional Collection Set", _cur_optional_evac_time_ms); 420 debug_phase(_gc_par_phases[OptScanHR]); 421 debug_phase(_gc_par_phases[OptObjCopy]); 422 debug_phase(_gc_par_phases[OptCodeRoots]); 423 debug_phase(_gc_par_phases[OptTermination]); 424 } 425 return sum_ms; 426 } 427 428 double G1GCPhaseTimes::print_evacuate_initial_collection_set() const { 429 info_time("Merge Heap Roots", _cur_merge_heap_roots_time_ms); 430 431 debug_time("Prepare Merge Heap Roots", _cur_prepare_merge_heap_roots_time_ms); 432 debug_phase(_gc_par_phases[MergeER]); 433 debug_phase(_gc_par_phases[MergeRS]); 434 if (G1HotCardCache::default_use_cache()) { 435 debug_phase(_gc_par_phases[MergeHCC]); 436 } 437 debug_phase(_gc_par_phases[MergeLB]); 438 439 info_time("Evacuate Collection Set", _cur_collection_initial_evac_time_ms); 440 441 trace_phase(_gc_par_phases[GCWorkerStart], false); 442 debug_phase(_gc_par_phases[ExtRootScan]); 443 for (int i = ExtRootScanSubPhasesFirst; i <= ExtRootScanSubPhasesLast; i++) { 444 trace_phase(_gc_par_phases[i]); 445 } 446 debug_phase(_gc_par_phases[ScanHR]); 447 debug_phase(_gc_par_phases[CodeRoots]); 448 debug_phase(_gc_par_phases[ObjCopy]); 449 debug_phase(_gc_par_phases[Termination]); 450 debug_phase(_gc_par_phases[Other]); 451 debug_phase(_gc_par_phases[GCWorkerTotal]); 452 trace_phase(_gc_par_phases[GCWorkerEnd], false); 453 454 return _cur_collection_initial_evac_time_ms + _cur_merge_heap_roots_time_ms; 455 } 456 457 double G1GCPhaseTimes::print_post_evacuate_collection_set() const { 458 const double evac_fail_handling = _cur_evac_fail_recalc_used + 459 _cur_evac_fail_remove_self_forwards; 460 assert(_gc_par_phases[MergePSS]->get(0) != WorkerDataArray<double>::uninitialized(), "must be set"); 461 const double merge_pss = _gc_par_phases[MergePSS]->get(0) * MILLIUNITS; 462 const double sum_ms = evac_fail_handling + 463 _cur_collection_code_root_fixup_time_ms + 464 _recorded_preserve_cm_referents_time_ms + 465 _cur_ref_proc_time_ms + 466 (_weak_phase_times.total_time_sec() * MILLIUNITS) + 467 _cur_clear_ct_time_ms + 468 merge_pss + 469 _cur_strong_code_root_purge_time_ms + 470 _recorded_redirty_logged_cards_time_ms + 471 _recorded_total_free_cset_time_ms + 472 _recorded_total_rebuild_freelist_time_ms + 473 _cur_fast_reclaim_humongous_time_ms + 474 _cur_expand_heap_time_ms + 475 _cur_string_deduplication_time_ms; 476 477 info_time("Post Evacuate Collection Set", sum_ms); 478 479 debug_time("Code Roots Fixup", _cur_collection_code_root_fixup_time_ms); 480 481 debug_time("Clear Card Table", _cur_clear_ct_time_ms); 482 483 debug_time_for_reference("Reference Processing", _cur_ref_proc_time_ms); 484 _ref_phase_times.print_all_references(2, false); 485 _weak_phase_times.log_print(2); 486 487 if (G1StringDedup::is_enabled()) { 488 debug_time("String Deduplication", _cur_string_deduplication_time_ms); 489 debug_phase(_gc_par_phases[StringDedupQueueFixup], 1); 490 debug_phase(_gc_par_phases[StringDedupTableFixup], 1); 491 } 492 493 if (G1CollectedHeap::heap()->evacuation_failed()) { 494 debug_time("Evacuation Failure", evac_fail_handling); 495 trace_time("Recalculate Used", _cur_evac_fail_recalc_used); 496 trace_time("Remove Self Forwards",_cur_evac_fail_remove_self_forwards); 497 } 498 499 debug_phase(_gc_par_phases[MergePSS], 0); 500 debug_time("Code Roots Purge", _cur_strong_code_root_purge_time_ms); 501 502 debug_time("Redirty Cards", _recorded_redirty_logged_cards_time_ms); 503 trace_phase(_gc_par_phases[RedirtyCards]); 504 #if COMPILER2_OR_JVMCI 505 debug_time("DerivedPointerTable Update", _cur_derived_pointer_table_update_time_ms); 506 #endif 507 508 debug_time("Free Collection Set", _recorded_total_free_cset_time_ms); 509 trace_time("Serial Free Collection Set", _recorded_serial_free_cset_time_ms); 510 trace_phase(_gc_par_phases[ParFreeCSet]); 511 trace_phase(_gc_par_phases[YoungFreeCSet], true, 1); 512 trace_phase(_gc_par_phases[NonYoungFreeCSet], true, 1); 513 514 debug_time("Rebuild Free List", _recorded_total_rebuild_freelist_time_ms); 515 trace_time("Serial Rebuild Free List ", _recorded_serial_rebuild_freelist_time_ms); 516 trace_phase(_gc_par_phases[RebuildFreeList]); 517 518 if (G1EagerReclaimHumongousObjects) { 519 debug_time("Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms); 520 trace_count("Humongous Reclaimed", _cur_fast_reclaim_humongous_reclaimed); 521 } 522 debug_time("Start New Collection Set", _recorded_start_new_cset_time_ms); 523 if (UseTLAB && ResizeTLAB) { 524 debug_time("Resize TLABs", _cur_resize_tlab_time_ms); 525 } 526 debug_time("Expand Heap After Collection", _cur_expand_heap_time_ms); 527 528 529 return sum_ms; 530 } 531 532 void G1GCPhaseTimes::print_other(double accounted_ms) const { 533 info_time("Other", _gc_pause_time_ms - accounted_ms); 534 } 535 536 void G1GCPhaseTimes::print() { 537 note_gc_end(); 538 539 if (_cur_verify_before_time_ms > 0.0) { 540 debug_time("Verify Before", _cur_verify_before_time_ms); 541 } 542 543 double accounted_ms = 0.0; 544 accounted_ms += print_pre_evacuate_collection_set(); 545 accounted_ms += print_evacuate_initial_collection_set(); 546 accounted_ms += print_evacuate_optional_collection_set(); 547 accounted_ms += print_post_evacuate_collection_set(); 548 print_other(accounted_ms); 549 550 if (_cur_verify_after_time_ms > 0.0) { 551 debug_time("Verify After", _cur_verify_after_time_ms); 552 } 553 } 554 555 const char* G1GCPhaseTimes::phase_name(GCParPhases phase) { 556 static const char* names[] = { 557 "GCWorkerStart", 558 "ExtRootScan", 559 "ThreadRoots", 560 "UniverseRoots", 561 "JNIRoots", 562 "ObjectSynchronizerRoots", 563 "ManagementRoots", 564 "VMGlobalRoots", 565 "CLDGRoots", 566 "JVMTIRoots", 567 AOT_ONLY("AOTCodeRoots" COMMA) 568 "CMRefRoots", 569 "MergeER", 570 "MergeRS", 571 "OptMergeRS", 572 "MergeLB", 573 "MergeHCC", 574 "ScanHR", 575 "OptScanHR", 576 "CodeRoots", 577 "OptCodeRoots", 578 "ObjCopy", 579 "OptObjCopy", 580 "Termination", 581 "OptTermination", 582 "Other", 583 "GCWorkerTotal", 584 "GCWorkerEnd", 585 "StringDedupQueueFixup", 586 "StringDedupTableFixup", 587 "RedirtyCards", 588 "ParFreeCSet", 589 "YoungFreeCSet", 590 "NonYoungFreeCSet", 591 "RebuildFreeList", 592 "MergePSS" 593 //GCParPhasesSentinel only used to tell end of enum 594 }; 595 596 STATIC_ASSERT(ARRAY_SIZE(names) == G1GCPhaseTimes::GCParPhasesSentinel); // GCParPhases enum and corresponding string array should have the same "length", this tries to assert it 597 598 return names[phase]; 599 } 600 601 G1EvacPhaseWithTrimTimeTracker::G1EvacPhaseWithTrimTimeTracker(G1ParScanThreadState* pss, Tickspan& total_time, Tickspan& trim_time) : 602 _pss(pss), 603 _start(Ticks::now()), 604 _total_time(total_time), 605 _trim_time(trim_time), 606 _stopped(false) { 607 608 assert(_pss->trim_ticks().value() == 0, "Possibly remaining trim ticks left over from previous use"); 609 } 610 611 G1EvacPhaseWithTrimTimeTracker::~G1EvacPhaseWithTrimTimeTracker() { 612 if (!_stopped) { 613 stop(); 614 } 615 } 616 617 void G1EvacPhaseWithTrimTimeTracker::stop() { 618 assert(!_stopped, "Should only be called once"); 619 _total_time += (Ticks::now() - _start) - _pss->trim_ticks(); 620 _trim_time += _pss->trim_ticks(); 621 _pss->reset_trim_ticks(); 622 _stopped = true; 623 } 624 625 G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id, bool must_record) : 626 _start_time(), _phase(phase), _phase_times(phase_times), _worker_id(worker_id), _event(), _must_record(must_record) { 627 if (_phase_times != NULL) { 628 _start_time = Ticks::now(); 629 } 630 } 631 632 G1GCParPhaseTimesTracker::~G1GCParPhaseTimesTracker() { 633 if (_phase_times != NULL) { 634 if (_must_record) { 635 _phase_times->record_time_secs(_phase, _worker_id, (Ticks::now() - _start_time).seconds()); 636 } else { 637 _phase_times->record_or_add_time_secs(_phase, _worker_id, (Ticks::now() - _start_time).seconds()); 638 } 639 _event.commit(GCId::current(), _worker_id, G1GCPhaseTimes::phase_name(_phase)); 640 } 641 } 642 643 G1EvacPhaseTimesTracker::G1EvacPhaseTimesTracker(G1GCPhaseTimes* phase_times, 644 G1ParScanThreadState* pss, 645 G1GCPhaseTimes::GCParPhases phase, 646 uint worker_id) : 647 G1GCParPhaseTimesTracker(phase_times, phase, worker_id), 648 _total_time(), 649 _trim_time(), 650 _trim_tracker(pss, _total_time, _trim_time) { 651 } 652 653 G1EvacPhaseTimesTracker::~G1EvacPhaseTimesTracker() { 654 if (_phase_times != NULL) { 655 // Explicitly stop the trim tracker since it's not yet destructed. 656 _trim_tracker.stop(); 657 // Exclude trim time by increasing the start time. 658 _start_time += _trim_time; 659 _phase_times->record_or_add_time_secs(G1GCPhaseTimes::ObjCopy, _worker_id, _trim_time.seconds()); 660 } 661 } 662