1 | /* |
2 | * Copyright (c) 2013, 2019, 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/referenceProcessorPhaseTimes.hpp" |
29 | #include "gc/shared/weakProcessorPhaseTimes.hpp" |
30 | #include "jfr/jfrEvents.hpp" |
31 | #include "logging/logLevel.hpp" |
32 | #include "memory/allocation.hpp" |
33 | #include "utilities/macros.hpp" |
34 | |
35 | class LineBuffer; |
36 | class G1ParScanThreadState; |
37 | class STWGCTimer; |
38 | |
39 | template <class T> class WorkerDataArray; |
40 | |
41 | class G1GCPhaseTimes : public CHeapObj<mtGC> { |
42 | uint _max_gc_threads; |
43 | jlong _gc_start_counter; |
44 | double _gc_pause_time_ms; |
45 | |
46 | public: |
47 | enum GCParPhases { |
48 | GCWorkerStart, |
49 | ExtRootScan, |
50 | ThreadRoots, |
51 | UniverseRoots, |
52 | JNIRoots, |
53 | ObjectSynchronizerRoots, |
54 | ManagementRoots, |
55 | SystemDictionaryRoots, |
56 | CLDGRoots, |
57 | JVMTIRoots, |
58 | AOT_ONLY(AOTCodeRoots COMMA) |
59 | JVMCI_ONLY(JVMCIRoots COMMA) |
60 | CMRefRoots, |
61 | WaitForStrongCLD, |
62 | WeakCLDRoots, |
63 | UpdateRS, |
64 | ScanHCC, |
65 | ScanRS, |
66 | OptScanRS, |
67 | CodeRoots, |
68 | OptCodeRoots, |
69 | ObjCopy, |
70 | OptObjCopy, |
71 | Termination, |
72 | OptTermination, |
73 | Other, |
74 | GCWorkerTotal, |
75 | GCWorkerEnd, |
76 | StringDedupQueueFixup, |
77 | StringDedupTableFixup, |
78 | RedirtyCards, |
79 | YoungFreeCSet, |
80 | NonYoungFreeCSet, |
81 | GCParPhasesSentinel |
82 | }; |
83 | |
84 | static const GCParPhases ExtRootScanSubPhasesFirst = ThreadRoots; |
85 | static const GCParPhases ExtRootScanSubPhasesLast = WeakCLDRoots; |
86 | |
87 | enum GCScanRSWorkItems { |
88 | , |
89 | ScanRSClaimedCards, |
90 | , |
91 | , |
92 | ScanRSUsedMemory |
93 | }; |
94 | |
95 | enum GCUpdateRSWorkItems { |
96 | UpdateRSProcessedBuffers, |
97 | , |
98 | |
99 | }; |
100 | |
101 | enum GCObjCopyWorkItems { |
102 | ObjCopyLABWaste, |
103 | ObjCopyLABUndoWaste |
104 | }; |
105 | |
106 | private: |
107 | // Markers for grouping the phases in the GCPhases enum above |
108 | static const int GCMainParPhasesLast = GCWorkerEnd; |
109 | |
110 | WorkerDataArray<double>* _gc_par_phases[GCParPhasesSentinel]; |
111 | |
112 | WorkerDataArray<size_t>* _update_rs_processed_buffers; |
113 | WorkerDataArray<size_t>* _update_rs_scanned_cards; |
114 | WorkerDataArray<size_t>* _update_rs_skipped_cards; |
115 | |
116 | WorkerDataArray<size_t>* _scan_rs_scanned_cards; |
117 | WorkerDataArray<size_t>* _scan_rs_claimed_cards; |
118 | WorkerDataArray<size_t>* _scan_rs_skipped_cards; |
119 | |
120 | WorkerDataArray<size_t>* _opt_scan_rs_scanned_cards; |
121 | WorkerDataArray<size_t>* _opt_scan_rs_claimed_cards; |
122 | WorkerDataArray<size_t>* _opt_scan_rs_skipped_cards; |
123 | WorkerDataArray<size_t>* _opt_scan_rs_scanned_opt_refs; |
124 | WorkerDataArray<size_t>* _opt_scan_rs_used_memory; |
125 | |
126 | WorkerDataArray<size_t>* _obj_copy_lab_waste; |
127 | WorkerDataArray<size_t>* _obj_copy_lab_undo_waste; |
128 | |
129 | WorkerDataArray<size_t>* _opt_obj_copy_lab_waste; |
130 | WorkerDataArray<size_t>* _opt_obj_copy_lab_undo_waste; |
131 | |
132 | WorkerDataArray<size_t>* _termination_attempts; |
133 | |
134 | WorkerDataArray<size_t>* _opt_termination_attempts; |
135 | |
136 | WorkerDataArray<size_t>* _redirtied_cards; |
137 | |
138 | double _cur_collection_initial_evac_time_ms; |
139 | double _cur_optional_evac_ms; |
140 | double _cur_collection_code_root_fixup_time_ms; |
141 | double _cur_strong_code_root_purge_time_ms; |
142 | |
143 | double _cur_evac_fail_recalc_used; |
144 | double _cur_evac_fail_remove_self_forwards; |
145 | |
146 | double _cur_string_deduplication_time_ms; |
147 | |
148 | double _cur_prepare_tlab_time_ms; |
149 | double _cur_resize_tlab_time_ms; |
150 | |
151 | double _cur_derived_pointer_table_update_time_ms; |
152 | |
153 | double _cur_clear_ct_time_ms; |
154 | double _cur_expand_heap_time_ms; |
155 | double _cur_ref_proc_time_ms; |
156 | |
157 | double _cur_collection_start_sec; |
158 | double _root_region_scan_wait_time_ms; |
159 | |
160 | double _external_accounted_time_ms; |
161 | |
162 | double _recorded_clear_claimed_marks_time_ms; |
163 | |
164 | double _recorded_young_cset_choice_time_ms; |
165 | double _recorded_non_young_cset_choice_time_ms; |
166 | |
167 | double _recorded_redirty_logged_cards_time_ms; |
168 | |
169 | double _recorded_preserve_cm_referents_time_ms; |
170 | |
171 | double _recorded_merge_pss_time_ms; |
172 | |
173 | double _recorded_start_new_cset_time_ms; |
174 | |
175 | double _recorded_total_free_cset_time_ms; |
176 | |
177 | double _recorded_serial_free_cset_time_ms; |
178 | |
179 | double _cur_region_register_time; |
180 | |
181 | double _cur_fast_reclaim_humongous_time_ms; |
182 | size_t _cur_fast_reclaim_humongous_total; |
183 | size_t _cur_fast_reclaim_humongous_candidates; |
184 | size_t _cur_fast_reclaim_humongous_reclaimed; |
185 | |
186 | double _cur_verify_before_time_ms; |
187 | double _cur_verify_after_time_ms; |
188 | |
189 | ReferenceProcessorPhaseTimes _ref_phase_times; |
190 | WeakProcessorPhaseTimes _weak_phase_times; |
191 | |
192 | double worker_time(GCParPhases phase, uint worker); |
193 | void note_gc_end(); |
194 | void reset(); |
195 | |
196 | template <class T> |
197 | void details(T* phase, const char* indent) const; |
198 | |
199 | void log_phase(WorkerDataArray<double>* phase, uint indent, outputStream* out, bool print_sum) const; |
200 | void debug_phase(WorkerDataArray<double>* phase, uint = 0) const; |
201 | void trace_phase(WorkerDataArray<double>* phase, bool print_sum = true) const; |
202 | |
203 | void info_time(const char* name, double value) const; |
204 | void debug_time(const char* name, double value) const; |
205 | // This will print logs for both 'gc+phases' and 'gc+phases+ref'. |
206 | void debug_time_for_reference(const char* name, double value) const; |
207 | void trace_time(const char* name, double value) const; |
208 | void trace_count(const char* name, size_t value) const; |
209 | |
210 | double print_pre_evacuate_collection_set() const; |
211 | double print_evacuate_collection_set() const; |
212 | double print_evacuate_optional_collection_set() const; |
213 | double print_post_evacuate_collection_set() const; |
214 | void print_other(double accounted_ms) const; |
215 | |
216 | public: |
217 | G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads); |
218 | void note_gc_start(); |
219 | void print(); |
220 | static const char* phase_name(GCParPhases phase); |
221 | |
222 | // record the time a phase took in seconds |
223 | void record_time_secs(GCParPhases phase, uint worker_i, double secs); |
224 | |
225 | // add a number of seconds to a phase |
226 | void add_time_secs(GCParPhases phase, uint worker_i, double secs); |
227 | |
228 | void record_or_add_time_secs(GCParPhases phase, uint worker_i, double secs); |
229 | |
230 | double get_time_secs(GCParPhases phase, uint worker_i); |
231 | |
232 | void record_thread_work_item(GCParPhases phase, uint worker_i, size_t count, uint index = 0); |
233 | |
234 | void record_or_add_thread_work_item(GCParPhases phase, uint worker_i, size_t count, uint index = 0); |
235 | |
236 | size_t get_thread_work_item(GCParPhases phase, uint worker_i, uint index = 0); |
237 | |
238 | // return the average time for a phase in milliseconds |
239 | double average_time_ms(GCParPhases phase); |
240 | |
241 | size_t sum_thread_work_items(GCParPhases phase, uint index = 0); |
242 | |
243 | public: |
244 | |
245 | void record_prepare_tlab_time_ms(double ms) { |
246 | _cur_prepare_tlab_time_ms = ms; |
247 | } |
248 | |
249 | void record_resize_tlab_time_ms(double ms) { |
250 | _cur_resize_tlab_time_ms = ms; |
251 | } |
252 | |
253 | void record_derived_pointer_table_update_time(double ms) { |
254 | _cur_derived_pointer_table_update_time_ms = ms; |
255 | } |
256 | |
257 | void record_clear_ct_time(double ms) { |
258 | _cur_clear_ct_time_ms = ms; |
259 | } |
260 | |
261 | void record_expand_heap_time(double ms) { |
262 | _cur_expand_heap_time_ms = ms; |
263 | } |
264 | |
265 | void record_initial_evac_time(double ms) { |
266 | _cur_collection_initial_evac_time_ms = ms; |
267 | } |
268 | |
269 | void record_or_add_optional_evac_time(double ms) { |
270 | _cur_optional_evac_ms += ms; |
271 | } |
272 | |
273 | void record_or_add_code_root_fixup_time(double ms) { |
274 | _cur_collection_code_root_fixup_time_ms += ms; |
275 | } |
276 | |
277 | void record_strong_code_root_purge_time(double ms) { |
278 | _cur_strong_code_root_purge_time_ms = ms; |
279 | } |
280 | |
281 | void record_evac_fail_recalc_used_time(double ms) { |
282 | _cur_evac_fail_recalc_used = ms; |
283 | } |
284 | |
285 | void record_evac_fail_remove_self_forwards(double ms) { |
286 | _cur_evac_fail_remove_self_forwards = ms; |
287 | } |
288 | |
289 | void record_string_deduplication_time(double ms) { |
290 | _cur_string_deduplication_time_ms = ms; |
291 | } |
292 | |
293 | void record_ref_proc_time(double ms) { |
294 | _cur_ref_proc_time_ms = ms; |
295 | } |
296 | |
297 | void record_root_region_scan_wait_time(double time_ms) { |
298 | _root_region_scan_wait_time_ms = time_ms; |
299 | } |
300 | |
301 | void record_total_free_cset_time_ms(double time_ms) { |
302 | _recorded_total_free_cset_time_ms = time_ms; |
303 | } |
304 | |
305 | void record_serial_free_cset_time_ms(double time_ms) { |
306 | _recorded_serial_free_cset_time_ms = time_ms; |
307 | } |
308 | |
309 | void record_register_regions(double time_ms, size_t total, size_t candidates) { |
310 | _cur_region_register_time = time_ms; |
311 | _cur_fast_reclaim_humongous_total = total; |
312 | _cur_fast_reclaim_humongous_candidates = candidates; |
313 | } |
314 | |
315 | void record_fast_reclaim_humongous_time_ms(double value, size_t reclaimed) { |
316 | _cur_fast_reclaim_humongous_time_ms = value; |
317 | _cur_fast_reclaim_humongous_reclaimed = reclaimed; |
318 | } |
319 | |
320 | void record_young_cset_choice_time_ms(double time_ms) { |
321 | _recorded_young_cset_choice_time_ms = time_ms; |
322 | } |
323 | |
324 | void record_non_young_cset_choice_time_ms(double time_ms) { |
325 | _recorded_non_young_cset_choice_time_ms = time_ms; |
326 | } |
327 | |
328 | void record_redirty_logged_cards_time_ms(double time_ms) { |
329 | _recorded_redirty_logged_cards_time_ms = time_ms; |
330 | } |
331 | |
332 | void record_preserve_cm_referents_time_ms(double time_ms) { |
333 | _recorded_preserve_cm_referents_time_ms = time_ms; |
334 | } |
335 | |
336 | void record_merge_pss_time_ms(double time_ms) { |
337 | _recorded_merge_pss_time_ms = time_ms; |
338 | } |
339 | |
340 | void record_start_new_cset_time_ms(double time_ms) { |
341 | _recorded_start_new_cset_time_ms = time_ms; |
342 | } |
343 | |
344 | void record_cur_collection_start_sec(double time_ms) { |
345 | _cur_collection_start_sec = time_ms; |
346 | } |
347 | |
348 | void record_verify_before_time_ms(double time_ms) { |
349 | _cur_verify_before_time_ms = time_ms; |
350 | } |
351 | |
352 | void record_verify_after_time_ms(double time_ms) { |
353 | _cur_verify_after_time_ms = time_ms; |
354 | } |
355 | |
356 | void inc_external_accounted_time_ms(double time_ms) { |
357 | _external_accounted_time_ms += time_ms; |
358 | } |
359 | |
360 | void record_clear_claimed_marks_time_ms(double recorded_clear_claimed_marks_time_ms) { |
361 | _recorded_clear_claimed_marks_time_ms = recorded_clear_claimed_marks_time_ms; |
362 | } |
363 | |
364 | double cur_collection_start_sec() { |
365 | return _cur_collection_start_sec; |
366 | } |
367 | |
368 | double cur_collection_par_time_ms() { |
369 | return _cur_collection_initial_evac_time_ms; |
370 | } |
371 | |
372 | double cur_clear_ct_time_ms() { |
373 | return _cur_clear_ct_time_ms; |
374 | } |
375 | |
376 | double cur_expand_heap_time_ms() { |
377 | return _cur_expand_heap_time_ms; |
378 | } |
379 | |
380 | double root_region_scan_wait_time_ms() { |
381 | return _root_region_scan_wait_time_ms; |
382 | } |
383 | |
384 | double young_cset_choice_time_ms() { |
385 | return _recorded_young_cset_choice_time_ms; |
386 | } |
387 | |
388 | double total_free_cset_time_ms() { |
389 | return _recorded_total_free_cset_time_ms; |
390 | } |
391 | |
392 | double non_young_cset_choice_time_ms() { |
393 | return _recorded_non_young_cset_choice_time_ms; |
394 | } |
395 | |
396 | double fast_reclaim_humongous_time_ms() { |
397 | return _cur_fast_reclaim_humongous_time_ms; |
398 | } |
399 | |
400 | ReferenceProcessorPhaseTimes* ref_phase_times() { return &_ref_phase_times; } |
401 | |
402 | WeakProcessorPhaseTimes* weak_phase_times() { return &_weak_phase_times; } |
403 | }; |
404 | |
405 | class G1EvacPhaseWithTrimTimeTracker : public StackObj { |
406 | G1ParScanThreadState* _pss; |
407 | Ticks _start; |
408 | |
409 | Tickspan& _total_time; |
410 | Tickspan& _trim_time; |
411 | |
412 | bool _stopped; |
413 | public: |
414 | G1EvacPhaseWithTrimTimeTracker(G1ParScanThreadState* pss, Tickspan& total_time, Tickspan& trim_time); |
415 | ~G1EvacPhaseWithTrimTimeTracker(); |
416 | |
417 | void stop(); |
418 | }; |
419 | |
420 | class G1GCParPhaseTimesTracker : public CHeapObj<mtGC> { |
421 | protected: |
422 | Ticks _start_time; |
423 | G1GCPhaseTimes::GCParPhases _phase; |
424 | G1GCPhaseTimes* _phase_times; |
425 | uint _worker_id; |
426 | EventGCPhaseParallel _event; |
427 | public: |
428 | G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id); |
429 | virtual ~G1GCParPhaseTimesTracker(); |
430 | }; |
431 | |
432 | class G1EvacPhaseTimesTracker : public G1GCParPhaseTimesTracker { |
433 | Tickspan _total_time; |
434 | Tickspan _trim_time; |
435 | |
436 | G1EvacPhaseWithTrimTimeTracker _trim_tracker; |
437 | public: |
438 | G1EvacPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1ParScanThreadState* pss, G1GCPhaseTimes::GCParPhases phase, uint worker_id); |
439 | virtual ~G1EvacPhaseTimesTracker(); |
440 | }; |
441 | |
442 | #endif // SHARE_GC_G1_G1GCPHASETIMES_HPP |
443 | |