1 /* 2 * Copyright (c) 2013, 2023, 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 #ifndef SHARE_GC_G1_G1GCPHASETIMES_HPP 26 #define SHARE_GC_G1_G1GCPHASETIMES_HPP 27 28 #include "gc/shared/oopStorageSet.hpp" 29 #include "gc/shared/referenceProcessorPhaseTimes.hpp" 30 #include "gc/shared/weakProcessorTimes.hpp" 31 #include "logging/logLevel.hpp" 32 #include "memory/allocation.hpp" 33 #include "utilities/enumIterator.hpp" 34 #include "utilities/macros.hpp" 35 36 class LineBuffer; 37 class G1ParScanThreadState; 38 class STWGCTimer; 39 40 template <class T> class WorkerDataArray; 41 42 class G1GCPhaseTimes : public CHeapObj<mtGC> { 43 uint _max_gc_threads; 44 jlong _gc_start_counter; 45 double _gc_pause_time_ms; 46 47 public: 48 enum GCParPhases { 49 RetireTLABsAndFlushLogs, 50 NonJavaThreadFlushLogs, 51 GCWorkerStart, 52 ExtRootScan, 53 ThreadRoots, 54 CLDGRoots, 55 CMRefRoots, 56 // For every strong OopStorage there will be one element in this enum, 57 // starting with StrongOopStorageSetRoots. 58 StrongOopStorageSetRoots, 59 MergeER = StrongOopStorageSetRoots + EnumRange<OopStorageSet::StrongId>().size(), 60 MergeRS, 61 OptMergeRS, 62 MergeLB, 63 ScanHR, 64 OptScanHR, 65 CodeRoots, 66 OptCodeRoots, 67 ObjCopy, 68 OptObjCopy, 69 Termination, 70 OptTermination, 71 Other, 72 GCWorkerTotal, 73 GCWorkerEnd, 74 RedirtyCards, 75 FreeCollectionSet, 76 YoungFreeCSet, 77 NonYoungFreeCSet, 78 ResizeThreadLABs, 79 RebuildFreeList, 80 SampleCollectionSetCandidates, 81 MergePSS, 82 RestoreEvacuationFailedRegions, 83 RemoveSelfForwards, 84 ClearCardTable, 85 RecalculateUsed, 86 #if COMPILER2_OR_JVMCI 87 UpdateDerivedPointers, 88 #endif 89 EagerlyReclaimHumongousObjects, 90 ProcessEvacuationFailedRegions, 91 ResetMarkingState, 92 NoteStartOfMark, 93 GCParPhasesSentinel 94 }; 95 96 static const GCParPhases ExtRootScanSubPhasesFirst = ThreadRoots; 97 static const GCParPhases ExtRootScanSubPhasesLast = GCParPhases(MergeER - 1); 98 99 static constexpr GCParPhases strong_oopstorage_phase(OopStorageSet::StrongId id) { 100 size_t index = EnumRange<OopStorageSet::StrongId>().index(id); 101 return GCParPhases(StrongOopStorageSetRoots + index); 102 } 103 104 enum GCMergeRSWorkItems : uint { 105 MergeRSMergedInline = 0, 106 MergeRSMergedArrayOfCards, 107 MergeRSMergedHowl, 108 MergeRSMergedFull, 109 MergeRSHowlInline, 110 MergeRSHowlArrayOfCards, 111 MergeRSHowlBitmap, 112 MergeRSHowlFull, 113 MergeRSCards, 114 MergeRSContainersSentinel 115 }; 116 117 static constexpr const char* GCMergeRSWorkItemsStrings[MergeRSContainersSentinel] = 118 { "Merged Inline:", "Merged ArrayOfCards:", "Merged Howl:", "Merged Full:", 119 "Merged Howl Inline:", "Merged Howl ArrayOfCards:", "Merged Howl BitMap:", "Merged Howl Full:", 120 "Merged Cards:" }; 121 122 enum GCScanHRWorkItems { 123 ScanHRScannedCards, 124 ScanHRScannedBlocks, 125 ScanHRClaimedChunks, 126 ScanHRFoundRoots, 127 ScanHRScannedOptRefs, 128 ScanHRUsedMemory 129 }; 130 131 enum GCMergeLBWorkItems { 132 MergeLBDirtyCards, 133 MergeLBSkippedCards 134 }; 135 136 enum GCCodeRootsWorkItems { 137 CodeRootsScannedNMethods 138 }; 139 140 enum GCMergePSSWorkItems { 141 MergePSSCopiedBytes, 142 MergePSSLABSize, 143 MergePSSLABWasteBytes, 144 MergePSSLABUndoWasteBytes, 145 MergePSSEvacFailExtra 146 }; 147 148 enum RestoreEvacFailureRegionsWorkItems { 149 RestoreEvacFailureRegionsEvacFailedNum, // How many regions experienced an evacuation failure (pinned or allocation failure) 150 RestoreEvacFailureRegionsPinnedNum, // How many regions were found as pinned. 151 RestoreEvacFailureRegionsAllocFailedNum // How many regions were found experiencing an allocation failure. 152 }; 153 154 enum RemoveSelfForwardsWorkItems { 155 RemoveSelfForwardChunksNum, 156 RemoveSelfForwardEmptyChunksNum, 157 RemoveSelfForwardObjectsNum, 158 RemoveSelfForwardObjectsBytes, 159 }; 160 161 enum GCEagerlyReclaimHumongousObjectsItems { 162 EagerlyReclaimNumTotal, 163 EagerlyReclaimNumCandidates, 164 EagerlyReclaimNumReclaimed 165 }; 166 167 private: 168 // Markers for grouping the phases in the GCPhases enum above 169 static const int GCMainParPhasesLast = GCWorkerEnd; 170 171 WorkerDataArray<double>* _gc_par_phases[GCParPhasesSentinel]; 172 173 double _cur_collection_initial_evac_time_ms; 174 double _cur_optional_evac_time_ms; 175 double _cur_collection_nmethod_list_cleanup_time_ms; 176 177 double _cur_merge_heap_roots_time_ms; 178 double _cur_optional_merge_heap_roots_time_ms; 179 180 double _cur_prepare_merge_heap_roots_time_ms; 181 double _cur_optional_prepare_merge_heap_roots_time_ms; 182 183 double _cur_distribute_log_buffers_time_ms; 184 185 double _cur_pre_evacuate_prepare_time_ms; 186 187 double _cur_post_evacuate_cleanup_1_time_ms; 188 double _cur_post_evacuate_cleanup_2_time_ms; 189 190 double _cur_expand_heap_time_ms; 191 double _cur_ref_proc_time_ms; 192 193 double _cur_collection_start_sec; 194 double _root_region_scan_wait_time_ms; 195 196 double _external_accounted_time_ms; 197 198 double _recorded_prepare_heap_roots_time_ms; 199 200 double _recorded_young_cset_choice_time_ms; 201 double _recorded_non_young_cset_choice_time_ms; 202 203 double _recorded_prepare_for_mutator_time_ms; 204 205 double _recorded_serial_free_cset_time_ms; 206 207 double _recorded_total_rebuild_freelist_time_ms; 208 209 double _recorded_serial_rebuild_freelist_time_ms; 210 211 double _cur_region_register_time; 212 213 double _cur_verify_before_time_ms; 214 double _cur_verify_after_time_ms; 215 216 ReferenceProcessorPhaseTimes _ref_phase_times; 217 WeakProcessorTimes _weak_phase_times; 218 219 double worker_time(GCParPhases phase, uint worker); 220 void reset(); 221 222 template <class T> 223 void details(T* phase, uint indent_level) const; 224 225 void print_thread_work_items(WorkerDataArray<double>* phase, uint indent_level, outputStream* out) const; 226 void debug_phase_merge_remset() const; 227 228 void log_work_items(WorkerDataArray<double>* phase, uint indent, outputStream* out) const; 229 void log_phase(WorkerDataArray<double>* phase, uint indent_level, outputStream* out, bool print_sum) const; 230 void debug_serial_phase(WorkerDataArray<double>* phase, uint extra_indent = 0) const; 231 void debug_phase(WorkerDataArray<double>* phase, uint extra_indent = 0) const; 232 void trace_phase(WorkerDataArray<double>* phase, bool print_sum = true, uint extra_indent = 0) const; 233 234 void info_time(const char* name, double value) const; 235 void debug_time(const char* name, double value) const; 236 // This will print logs for both 'gc+phases' and 'gc+phases+ref'. 237 void debug_time_for_reference(const char* name, double value) const; 238 void trace_time(const char* name, double value) const; 239 void trace_count(const char* name, size_t value) const; 240 241 double print_pre_evacuate_collection_set() const; 242 double print_merge_heap_roots_time() const; 243 double print_evacuate_initial_collection_set() const; 244 double print_evacuate_optional_collection_set() const; 245 double print_post_evacuate_collection_set(bool evacuation_failed) const; 246 void print_other(double accounted_ms) const; 247 248 public: 249 G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads); 250 void record_gc_pause_start(); 251 void record_gc_pause_end(); 252 void print(bool evacuation_failed); 253 static const char* phase_name(GCParPhases phase); 254 255 // record the time a phase took in seconds 256 void record_time_secs(GCParPhases phase, uint worker_id, double secs); 257 258 // add a number of seconds to a phase 259 void add_time_secs(GCParPhases phase, uint worker_id, double secs); 260 261 void record_or_add_time_secs(GCParPhases phase, uint worker_id, double secs); 262 263 double get_time_secs(GCParPhases phase, uint worker_id); 264 265 void record_thread_work_item(GCParPhases phase, uint worker_id, size_t count, uint index = 0); 266 267 void record_or_add_thread_work_item(GCParPhases phase, uint worker_id, size_t count, uint index = 0); 268 269 size_t get_thread_work_item(GCParPhases phase, uint worker_id, uint index = 0); 270 271 // return the average time for a phase in milliseconds 272 double average_time_ms(GCParPhases phase) const; 273 274 size_t sum_thread_work_items(GCParPhases phase, uint index = 0); 275 276 void record_pre_evacuate_prepare_time_ms(double ms) { 277 _cur_pre_evacuate_prepare_time_ms = ms; 278 } 279 280 void record_expand_heap_time(double ms) { 281 _cur_expand_heap_time_ms = ms; 282 } 283 284 void record_initial_evac_time(double ms) { 285 _cur_collection_initial_evac_time_ms = ms; 286 } 287 288 void record_or_add_optional_evac_time(double ms) { 289 _cur_optional_evac_time_ms += ms; 290 } 291 292 void record_or_add_nmethod_list_cleanup_time(double ms) { 293 _cur_collection_nmethod_list_cleanup_time_ms += ms; 294 } 295 296 void record_merge_heap_roots_time(double ms) { 297 _cur_merge_heap_roots_time_ms += ms; 298 } 299 300 void record_or_add_optional_merge_heap_roots_time(double ms) { 301 _cur_optional_merge_heap_roots_time_ms += ms; 302 } 303 304 void record_prepare_merge_heap_roots_time(double ms) { 305 _cur_prepare_merge_heap_roots_time_ms += ms; 306 } 307 308 void record_distribute_log_buffers_time_ms(double ms) { 309 _cur_distribute_log_buffers_time_ms += ms; 310 } 311 312 void record_or_add_optional_prepare_merge_heap_roots_time(double ms) { 313 _cur_optional_prepare_merge_heap_roots_time_ms += ms; 314 } 315 316 void record_ref_proc_time(double ms) { 317 _cur_ref_proc_time_ms = ms; 318 } 319 320 void record_root_region_scan_wait_time(double time_ms) { 321 _root_region_scan_wait_time_ms = time_ms; 322 } 323 324 void record_serial_free_cset_time_ms(double time_ms) { 325 _recorded_serial_free_cset_time_ms = time_ms; 326 } 327 328 void record_total_rebuild_freelist_time_ms(double time_ms) { 329 _recorded_total_rebuild_freelist_time_ms = time_ms; 330 } 331 332 void record_serial_rebuild_freelist_time_ms(double time_ms) { 333 _recorded_serial_rebuild_freelist_time_ms = time_ms; 334 } 335 336 void record_register_regions(double time_ms) { 337 _cur_region_register_time = time_ms; 338 } 339 340 void record_post_evacuate_cleanup_task_1_time(double time_ms) { 341 _cur_post_evacuate_cleanup_1_time_ms = time_ms; 342 } 343 344 void record_post_evacuate_cleanup_task_2_time(double time_ms) { 345 _cur_post_evacuate_cleanup_2_time_ms = time_ms; 346 } 347 348 void record_young_cset_choice_time_ms(double time_ms) { 349 _recorded_young_cset_choice_time_ms = time_ms; 350 } 351 352 void record_non_young_cset_choice_time_ms(double time_ms) { 353 _recorded_non_young_cset_choice_time_ms = time_ms; 354 } 355 356 void record_prepare_for_mutator_time_ms(double time_ms) { 357 _recorded_prepare_for_mutator_time_ms = time_ms; 358 } 359 360 void record_cur_collection_start_sec(double time_ms) { 361 _cur_collection_start_sec = time_ms; 362 } 363 364 void record_verify_before_time_ms(double time_ms) { 365 _cur_verify_before_time_ms = time_ms; 366 } 367 368 void record_verify_after_time_ms(double time_ms) { 369 _cur_verify_after_time_ms = time_ms; 370 } 371 372 void inc_external_accounted_time_ms(double time_ms) { 373 _external_accounted_time_ms += time_ms; 374 } 375 376 void record_prepare_heap_roots_time_ms(double recorded_prepare_heap_roots_time_ms) { 377 _recorded_prepare_heap_roots_time_ms = recorded_prepare_heap_roots_time_ms; 378 } 379 380 double cur_collection_start_sec() { 381 return _cur_collection_start_sec; 382 } 383 384 double cur_distribute_log_buffers_time_ms() { 385 return _cur_distribute_log_buffers_time_ms; 386 } 387 388 double cur_collection_par_time_ms() { 389 return _cur_collection_initial_evac_time_ms + 390 _cur_optional_evac_time_ms + 391 _cur_merge_heap_roots_time_ms + 392 _cur_optional_merge_heap_roots_time_ms; 393 } 394 395 double cur_expand_heap_time_ms() { 396 return _cur_expand_heap_time_ms; 397 } 398 399 double root_region_scan_wait_time_ms() { 400 return _root_region_scan_wait_time_ms; 401 } 402 403 double young_cset_choice_time_ms() { 404 return _recorded_young_cset_choice_time_ms; 405 } 406 407 double total_rebuild_freelist_time_ms() { 408 return _recorded_total_rebuild_freelist_time_ms; 409 } 410 411 double non_young_cset_choice_time_ms() { 412 return _recorded_non_young_cset_choice_time_ms; 413 } 414 415 ReferenceProcessorPhaseTimes* ref_phase_times() { return &_ref_phase_times; } 416 417 WeakProcessorTimes* weak_phase_times() { return &_weak_phase_times; } 418 }; 419 420 class G1EvacPhaseWithTrimTimeTracker : public StackObj { 421 G1ParScanThreadState* _pss; 422 Ticks _start; 423 424 Tickspan& _total_time; 425 Tickspan& _trim_time; 426 427 bool _stopped; 428 public: 429 G1EvacPhaseWithTrimTimeTracker(G1ParScanThreadState* pss, Tickspan& total_time, Tickspan& trim_time); 430 ~G1EvacPhaseWithTrimTimeTracker(); 431 432 void stop(); 433 }; 434 435 #endif // SHARE_GC_G1_G1GCPHASETIMES_HPP