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