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
--- EOF ---