Thu, 23 Aug 2012 10:21:12 +0200
7178363: G1: Remove the serial code for PrintGCDetails and make it a special case of the parallel code
Summary: Also reviewed by vitalyd@gmail.com. Introduced the WorkerDataArray class. Fixed some minor logging bugs.
Reviewed-by: johnc, mgerdin
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 */
25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
28 #include "memory/allocation.hpp"
29 #include "gc_interface/gcCause.hpp"
31 template <class T>
32 class WorkerDataArray : public CHeapObj<mtGC> {
33 T* _data;
34 uint _length;
35 const char* _print_format;
36 bool _print_sum;
38 // We are caching the sum and average to only have to calculate them once.
39 // This is not done in an MT-safe way. It is intetened to allow single
40 // threaded code to call sum() and average() multiple times in any order
41 // without having to worry about the cost.
42 bool _has_new_data;
43 T _sum;
44 double _average;
46 public:
47 WorkerDataArray(uint length, const char* print_format, bool print_sum = true) :
48 _length(length), _print_format(print_format), _print_sum(print_sum), _has_new_data(true) {
49 assert(length > 0, "Must have some workers to store data for");
50 _data = NEW_C_HEAP_ARRAY(T, _length, mtGC);
51 }
53 ~WorkerDataArray() {
54 FREE_C_HEAP_ARRAY(T, _data, mtGC);
55 }
57 void set(uint worker_i, T value) {
58 assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
59 assert(_data[worker_i] == (T)-1, err_msg("Overwriting data for worker %d", worker_i));
60 _data[worker_i] = value;
61 _has_new_data = true;
62 }
64 T get(uint worker_i) {
65 assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
66 assert(_data[worker_i] != (T)-1, err_msg("No data to add to for worker %d", worker_i));
67 return _data[worker_i];
68 }
70 void add(uint worker_i, T value) {
71 assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
72 assert(_data[worker_i] != (T)-1, err_msg("No data to add to for worker %d", worker_i));
73 _data[worker_i] += value;
74 _has_new_data = true;
75 }
77 double average(){
78 if (_has_new_data) {
79 calculate_totals();
80 }
81 return _average;
82 }
84 T sum() {
85 if (_has_new_data) {
86 calculate_totals();
87 }
88 return _sum;
89 }
91 void print(int level, const char* title);
93 void reset() PRODUCT_RETURN;
94 void verify() PRODUCT_RETURN;
96 private:
98 void calculate_totals(){
99 _sum = (T)0;
100 for (uint i = 0; i < _length; ++i) {
101 _sum += _data[i];
102 }
103 _average = (double)_sum / (double)_length;
104 _has_new_data = false;
105 }
106 };
108 class G1GCPhaseTimes : public CHeapObj<mtGC> {
110 private:
111 uint _active_gc_threads;
112 uint _max_gc_threads;
114 WorkerDataArray<double> _last_gc_worker_start_times_ms;
115 WorkerDataArray<double> _last_ext_root_scan_times_ms;
116 WorkerDataArray<double> _last_satb_filtering_times_ms;
117 WorkerDataArray<double> _last_update_rs_times_ms;
118 WorkerDataArray<int> _last_update_rs_processed_buffers;
119 WorkerDataArray<double> _last_scan_rs_times_ms;
120 WorkerDataArray<double> _last_obj_copy_times_ms;
121 WorkerDataArray<double> _last_termination_times_ms;
122 WorkerDataArray<size_t> _last_termination_attempts;
123 WorkerDataArray<double> _last_gc_worker_end_times_ms;
124 WorkerDataArray<double> _last_gc_worker_times_ms;
125 WorkerDataArray<double> _last_gc_worker_other_times_ms;
127 double _cur_collection_par_time_ms;
128 double _cur_collection_code_root_fixup_time_ms;
130 double _cur_clear_ct_time_ms;
131 double _cur_ref_proc_time_ms;
132 double _cur_ref_enq_time_ms;
134 // Card Table Count Cache stats
135 double _min_clear_cc_time_ms; // min
136 double _max_clear_cc_time_ms; // max
137 double _cur_clear_cc_time_ms; // clearing time during current pause
138 double _cum_clear_cc_time_ms; // cummulative clearing time
139 jlong _num_cc_clears; // number of times the card count cache has been cleared
141 double _cur_collection_start_sec;
142 double _root_region_scan_wait_time_ms;
144 double _recorded_young_cset_choice_time_ms;
145 double _recorded_non_young_cset_choice_time_ms;
147 double _recorded_young_free_cset_time_ms;
148 double _recorded_non_young_free_cset_time_ms;
150 double _cur_verify_before_time_ms;
151 double _cur_verify_after_time_ms;
153 // Helper methods for detailed logging
154 void print_stats(int level, const char* str, double value);
155 void print_stats(int level, const char* str, double value, int workers);
157 public:
158 G1GCPhaseTimes(uint max_gc_threads);
159 void note_gc_start(uint active_gc_threads);
160 void note_gc_end();
161 void print(double pause_time_sec);
163 void record_gc_worker_start_time(uint worker_i, double ms) {
164 _last_gc_worker_start_times_ms.set(worker_i, ms);
165 }
167 void record_ext_root_scan_time(uint worker_i, double ms) {
168 _last_ext_root_scan_times_ms.set(worker_i, ms);
169 }
171 void record_satb_filtering_time(uint worker_i, double ms) {
172 _last_satb_filtering_times_ms.set(worker_i, ms);
173 }
175 void record_update_rs_time(uint worker_i, double ms) {
176 _last_update_rs_times_ms.set(worker_i, ms);
177 }
179 void record_update_rs_processed_buffers(uint worker_i, int processed_buffers) {
180 _last_update_rs_processed_buffers.set(worker_i, processed_buffers);
181 }
183 void record_scan_rs_time(uint worker_i, double ms) {
184 _last_scan_rs_times_ms.set(worker_i, ms);
185 }
187 void record_obj_copy_time(uint worker_i, double ms) {
188 _last_obj_copy_times_ms.set(worker_i, ms);
189 }
191 void add_obj_copy_time(uint worker_i, double ms) {
192 _last_obj_copy_times_ms.add(worker_i, ms);
193 }
195 void record_termination(uint worker_i, double ms, size_t attempts) {
196 _last_termination_times_ms.set(worker_i, ms);
197 _last_termination_attempts.set(worker_i, attempts);
198 }
200 void record_gc_worker_end_time(uint worker_i, double ms) {
201 _last_gc_worker_end_times_ms.set(worker_i, ms);
202 }
204 void record_clear_ct_time(double ms) {
205 _cur_clear_ct_time_ms = ms;
206 }
208 void record_par_time(double ms) {
209 _cur_collection_par_time_ms = ms;
210 }
212 void record_code_root_fixup_time(double ms) {
213 _cur_collection_code_root_fixup_time_ms = ms;
214 }
216 void record_ref_proc_time(double ms) {
217 _cur_ref_proc_time_ms = ms;
218 }
220 void record_ref_enq_time(double ms) {
221 _cur_ref_enq_time_ms = ms;
222 }
224 void record_root_region_scan_wait_time(double time_ms) {
225 _root_region_scan_wait_time_ms = time_ms;
226 }
228 void record_cc_clear_time_ms(double ms);
230 void record_young_free_cset_time_ms(double time_ms) {
231 _recorded_young_free_cset_time_ms = time_ms;
232 }
234 void record_non_young_free_cset_time_ms(double time_ms) {
235 _recorded_non_young_free_cset_time_ms = time_ms;
236 }
238 void record_young_cset_choice_time_ms(double time_ms) {
239 _recorded_young_cset_choice_time_ms = time_ms;
240 }
242 void record_non_young_cset_choice_time_ms(double time_ms) {
243 _recorded_non_young_cset_choice_time_ms = time_ms;
244 }
246 void record_cur_collection_start_sec(double time_ms) {
247 _cur_collection_start_sec = time_ms;
248 }
250 void record_verify_before_time_ms(double time_ms) {
251 _cur_verify_before_time_ms = time_ms;
252 }
254 void record_verify_after_time_ms(double time_ms) {
255 _cur_verify_after_time_ms = time_ms;
256 }
258 double accounted_time_ms();
260 double cur_collection_start_sec() {
261 return _cur_collection_start_sec;
262 }
264 double cur_collection_par_time_ms() {
265 return _cur_collection_par_time_ms;
266 }
268 double cur_clear_ct_time_ms() {
269 return _cur_clear_ct_time_ms;
270 }
272 double root_region_scan_wait_time_ms() {
273 return _root_region_scan_wait_time_ms;
274 }
276 double young_cset_choice_time_ms() {
277 return _recorded_young_cset_choice_time_ms;
278 }
280 double young_free_cset_time_ms() {
281 return _recorded_young_free_cset_time_ms;
282 }
284 double non_young_cset_choice_time_ms() {
285 return _recorded_non_young_cset_choice_time_ms;
286 }
288 double non_young_free_cset_time_ms() {
289 return _recorded_non_young_free_cset_time_ms;
290 }
292 double average_last_update_rs_time() {
293 return _last_update_rs_times_ms.average();
294 }
296 int sum_last_update_rs_processed_buffers() {
297 return _last_update_rs_processed_buffers.sum();
298 }
300 double average_last_scan_rs_time(){
301 return _last_scan_rs_times_ms.average();
302 }
304 double average_last_obj_copy_time() {
305 return _last_obj_copy_times_ms.average();
306 }
308 double average_last_termination_time() {
309 return _last_termination_times_ms.average();
310 }
312 double average_last_ext_root_scan_time() {
313 return _last_ext_root_scan_times_ms.average();
314 }
316 double average_last_satb_filtering_times_ms() {
317 return _last_satb_filtering_times_ms.average();
318 }
319 };
321 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP