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