1 /* 2 * Copyright (c) 2012, 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_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP 27 28 #include "memory/allocation.hpp" 29 #include "gc_interface/gcCause.hpp" 30 31 class G1GCPhaseTimes : public CHeapObj<mtGC> { 32 friend class G1CollectorPolicy; 33 friend class TraceGen0TimeData; 34 35 private: 36 uint _active_gc_threads; 37 uint _max_gc_threads; 38 39 GCCause::Cause _gc_cause; 40 bool _is_young_gc; 41 bool _is_initial_mark_gc; 42 43 double _pause_start_time_sec; 44 45 double* _par_last_gc_worker_start_times_ms; 46 double* _par_last_ext_root_scan_times_ms; 47 double* _par_last_satb_filtering_times_ms; 48 double* _par_last_update_rs_times_ms; 49 double* _par_last_update_rs_processed_buffers; 50 double* _par_last_scan_rs_times_ms; 51 double* _par_last_obj_copy_times_ms; 52 double* _par_last_termination_times_ms; 53 double* _par_last_termination_attempts; 54 double* _par_last_gc_worker_end_times_ms; 55 double* _par_last_gc_worker_times_ms; 56 double* _par_last_gc_worker_other_times_ms; 57 58 double _cur_collection_par_time_ms; 59 60 double _cur_collection_code_root_fixup_time_ms; 61 62 double _cur_clear_ct_time_ms; 63 double _cur_ref_proc_time_ms; 64 double _cur_ref_enq_time_ms; 65 66 // Helper methods for detailed logging 67 void print_par_stats(int level, const char* str, double* data, bool showDecimals = true); 68 void print_stats(int level, const char* str, double value); 69 void print_stats(int level, const char* str, double value, int workers); 70 void print_stats(int level, const char* str, int value); 71 double avg_value(double* data); 72 double max_value(double* data); 73 double sum_of_values(double* data); 74 double max_sum(double* data1, double* data2); 75 double accounted_time_ms(); 76 77 // Card Table Count Cache stats 78 double _min_clear_cc_time_ms; // min 79 double _max_clear_cc_time_ms; // max 80 double _cur_clear_cc_time_ms; // clearing time during current pause 81 double _cum_clear_cc_time_ms; // cummulative clearing time 82 jlong _num_cc_clears; // number of times the card count cache has been cleared 83 84 // The following insance variables are directly accessed by G1CollectorPolicy 85 // and TraceGen0TimeData. This is why those classes are declared friends. 86 // An alternative is to add getters and setters for all of these fields. 87 // It might also be possible to restructure the code to reduce these 88 // dependencies. 89 double _ext_root_scan_time; 90 double _satb_filtering_time; 91 double _update_rs_time; 92 double _update_rs_processed_buffers; 93 double _scan_rs_time; 94 double _obj_copy_time; 95 double _termination_time; 96 97 double _cur_collection_start_sec; 98 double _root_region_scan_wait_time_ms; 99 100 double _recorded_young_cset_choice_time_ms; 101 double _recorded_non_young_cset_choice_time_ms; 102 103 double _recorded_young_free_cset_time_ms; 104 double _recorded_non_young_free_cset_time_ms; 105 106 void print(double pause_time_ms); 107 108 public: 109 G1GCPhaseTimes(uint max_gc_threads); 110 void note_gc_start(double pause_start_time_sec, uint active_gc_threads, 111 bool is_young_gc, bool is_initial_mark_gc, GCCause::Cause gc_cause); 112 void note_gc_end(double pause_end_time_sec); 113 void collapse_par_times(); 114 115 void record_gc_worker_start_time(uint worker_i, double ms) { 116 assert(worker_i >= 0, "worker index must be > 0"); 117 assert(worker_i < _active_gc_threads, "worker index out of bounds"); 118 _par_last_gc_worker_start_times_ms[worker_i] = ms; 119 } 120 121 void record_ext_root_scan_time(uint worker_i, double ms) { 122 assert(worker_i >= 0, "worker index must be > 0"); 123 assert(worker_i < _active_gc_threads, "worker index out of bounds"); 124 _par_last_ext_root_scan_times_ms[worker_i] = ms; 125 } 126 127 void record_satb_filtering_time(uint worker_i, double ms) { 128 assert(worker_i >= 0, "worker index must be > 0"); 129 assert(worker_i < _active_gc_threads, "worker index out of bounds"); 130 _par_last_satb_filtering_times_ms[worker_i] = ms; 131 } 132 133 void record_update_rs_time(uint worker_i, double ms) { 134 assert(worker_i >= 0, "worker index must be > 0"); 135 assert(worker_i < _active_gc_threads, "worker index out of bounds"); 136 _par_last_update_rs_times_ms[worker_i] = ms; 137 } 138 139 void record_update_rs_processed_buffers (uint worker_i, 140 double processed_buffers) { 141 assert(worker_i >= 0, "worker index must be > 0"); 142 assert(worker_i < _active_gc_threads, "worker index out of bounds"); 143 _par_last_update_rs_processed_buffers[worker_i] = processed_buffers; 144 } 145 146 void record_scan_rs_time(uint worker_i, double ms) { 147 assert(worker_i >= 0, "worker index must be > 0"); 148 assert(worker_i < _active_gc_threads, "worker index out of bounds"); 149 _par_last_scan_rs_times_ms[worker_i] = ms; 150 } 151 152 void reset_obj_copy_time(uint worker_i) { 153 assert(worker_i >= 0, "worker index must be > 0"); 154 assert(worker_i < _active_gc_threads, "worker index out of bounds"); 155 _par_last_obj_copy_times_ms[worker_i] = 0.0; 156 } 157 158 void reset_obj_copy_time() { 159 reset_obj_copy_time(0); 160 } 161 162 void record_obj_copy_time(uint worker_i, double ms) { 163 assert(worker_i >= 0, "worker index must be > 0"); 164 assert(worker_i < _active_gc_threads, "worker index out of bounds"); 165 _par_last_obj_copy_times_ms[worker_i] += ms; 166 } 167 168 void record_termination(uint worker_i, double ms, size_t attempts) { 169 assert(worker_i >= 0, "worker index must be > 0"); 170 assert(worker_i < _active_gc_threads, "worker index out of bounds"); 171 _par_last_termination_times_ms[worker_i] = ms; 172 _par_last_termination_attempts[worker_i] = (double) attempts; 173 } 174 175 void record_gc_worker_end_time(uint worker_i, double ms) { 176 assert(worker_i >= 0, "worker index must be > 0"); 177 assert(worker_i < _active_gc_threads, "worker index out of bounds"); 178 _par_last_gc_worker_end_times_ms[worker_i] = ms; 179 } 180 181 void record_clear_ct_time(double ms) { 182 _cur_clear_ct_time_ms = ms; 183 } 184 185 void record_par_time(double ms) { 186 _cur_collection_par_time_ms = ms; 187 } 188 189 void record_code_root_fixup_time(double ms) { 190 _cur_collection_code_root_fixup_time_ms = ms; 191 } 192 193 void record_ref_proc_time(double ms) { 194 _cur_ref_proc_time_ms = ms; 195 } 196 197 void record_ref_enq_time(double ms) { 198 _cur_ref_enq_time_ms = ms; 199 } 200 201 void record_root_region_scan_wait_time(double time_ms) { 202 _root_region_scan_wait_time_ms = time_ms; 203 } 204 205 void record_cc_clear_time_ms(double ms); 206 207 void record_young_free_cset_time_ms(double time_ms) { 208 _recorded_young_free_cset_time_ms = time_ms; 209 } 210 211 void record_non_young_free_cset_time_ms(double time_ms) { 212 _recorded_non_young_free_cset_time_ms = time_ms; 213 } 214 }; 215 216 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP