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