Thu, 21 Aug 2014 16:44:41 +0200
8055098: WB API should be extended to provide information about size and age of object.
Summary: Extend the WhiteBox API to provide information about the size and age of objects. Further add a mechanism to trigger a young GC.
Reviewed-by: tschatzl, sjohanss
Contributed-by: Leonid Mesnik <leonid.mesnik@oracle.com>
1 /*
2 * Copyright (c) 2013, 2014 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 NOT_PRODUCT(static const T _uninitialized;)
40 // We are caching the sum and average to only have to calculate them once.
41 // This is not done in an MT-safe way. It is intended to allow single
42 // threaded code to call sum() and average() multiple times in any order
43 // without having to worry about the cost.
44 bool _has_new_data;
45 T _sum;
46 double _average;
48 public:
49 WorkerDataArray(uint length, const char* print_format, bool print_sum = true) :
50 _length(length), _print_format(print_format), _print_sum(print_sum), _has_new_data(true) {
51 assert(length > 0, "Must have some workers to store data for");
52 _data = NEW_C_HEAP_ARRAY(T, _length, mtGC);
53 }
55 ~WorkerDataArray() {
56 FREE_C_HEAP_ARRAY(T, _data, mtGC);
57 }
59 void set(uint worker_i, T value) {
60 assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
61 assert(_data[worker_i] == (T)-1, err_msg("Overwriting data for worker %d", worker_i));
62 _data[worker_i] = value;
63 _has_new_data = true;
64 }
66 T get(uint worker_i) {
67 assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
68 assert(_data[worker_i] != (T)-1, err_msg("No data to add to for worker %d", worker_i));
69 return _data[worker_i];
70 }
72 void add(uint worker_i, T value) {
73 assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
74 assert(_data[worker_i] != (T)-1, err_msg("No data to add to for worker %d", worker_i));
75 _data[worker_i] += value;
76 _has_new_data = true;
77 }
79 double average(){
80 if (_has_new_data) {
81 calculate_totals();
82 }
83 return _average;
84 }
86 T sum() {
87 if (_has_new_data) {
88 calculate_totals();
89 }
90 return _sum;
91 }
93 void print(int level, const char* title);
95 void reset() PRODUCT_RETURN;
96 void verify() PRODUCT_RETURN;
98 private:
100 void calculate_totals(){
101 _sum = (T)0;
102 for (uint i = 0; i < _length; ++i) {
103 _sum += _data[i];
104 }
105 _average = (double)_sum / (double)_length;
106 _has_new_data = false;
107 }
108 };
110 class G1GCPhaseTimes : public CHeapObj<mtGC> {
112 private:
113 uint _active_gc_threads;
114 uint _max_gc_threads;
116 WorkerDataArray<double> _last_gc_worker_start_times_ms;
117 WorkerDataArray<double> _last_ext_root_scan_times_ms;
118 WorkerDataArray<double> _last_satb_filtering_times_ms;
119 WorkerDataArray<double> _last_update_rs_times_ms;
120 WorkerDataArray<int> _last_update_rs_processed_buffers;
121 WorkerDataArray<double> _last_scan_rs_times_ms;
122 WorkerDataArray<double> _last_strong_code_root_scan_times_ms;
123 WorkerDataArray<double> _last_obj_copy_times_ms;
124 WorkerDataArray<double> _last_termination_times_ms;
125 WorkerDataArray<size_t> _last_termination_attempts;
126 WorkerDataArray<double> _last_gc_worker_end_times_ms;
127 WorkerDataArray<double> _last_gc_worker_times_ms;
128 WorkerDataArray<double> _last_gc_worker_other_times_ms;
130 double _cur_collection_par_time_ms;
131 double _cur_collection_code_root_fixup_time_ms;
132 double _cur_strong_code_root_migration_time_ms;
133 double _cur_strong_code_root_purge_time_ms;
135 double _cur_evac_fail_recalc_used;
136 double _cur_evac_fail_restore_remsets;
137 double _cur_evac_fail_remove_self_forwards;
139 double _cur_string_dedup_fixup_time_ms;
140 WorkerDataArray<double> _cur_string_dedup_queue_fixup_worker_times_ms;
141 WorkerDataArray<double> _cur_string_dedup_table_fixup_worker_times_ms;
143 double _cur_clear_ct_time_ms;
144 double _cur_ref_proc_time_ms;
145 double _cur_ref_enq_time_ms;
147 double _cur_collection_start_sec;
148 double _root_region_scan_wait_time_ms;
150 double _recorded_young_cset_choice_time_ms;
151 double _recorded_non_young_cset_choice_time_ms;
153 WorkerDataArray<double> _last_redirty_logged_cards_time_ms;
154 WorkerDataArray<size_t> _last_redirty_logged_cards_processed_cards;
155 double _recorded_redirty_logged_cards_time_ms;
157 double _recorded_young_free_cset_time_ms;
158 double _recorded_non_young_free_cset_time_ms;
160 double _cur_fast_reclaim_humongous_time_ms;
161 size_t _cur_fast_reclaim_humongous_total;
162 size_t _cur_fast_reclaim_humongous_candidates;
163 size_t _cur_fast_reclaim_humongous_reclaimed;
165 double _cur_verify_before_time_ms;
166 double _cur_verify_after_time_ms;
168 // Helper methods for detailed logging
169 void print_stats(int level, const char* str, double value);
170 void print_stats(int level, const char* str, size_t value);
171 void print_stats(int level, const char* str, double value, uint workers);
173 public:
174 G1GCPhaseTimes(uint max_gc_threads);
175 void note_gc_start(uint active_gc_threads);
176 void note_gc_end();
177 void print(double pause_time_sec);
179 void record_gc_worker_start_time(uint worker_i, double ms) {
180 _last_gc_worker_start_times_ms.set(worker_i, ms);
181 }
183 void record_ext_root_scan_time(uint worker_i, double ms) {
184 _last_ext_root_scan_times_ms.set(worker_i, ms);
185 }
187 void record_satb_filtering_time(uint worker_i, double ms) {
188 _last_satb_filtering_times_ms.set(worker_i, ms);
189 }
191 void record_update_rs_time(uint worker_i, double ms) {
192 _last_update_rs_times_ms.set(worker_i, ms);
193 }
195 void record_update_rs_processed_buffers(uint worker_i, int processed_buffers) {
196 _last_update_rs_processed_buffers.set(worker_i, processed_buffers);
197 }
199 void record_scan_rs_time(uint worker_i, double ms) {
200 _last_scan_rs_times_ms.set(worker_i, ms);
201 }
203 void record_strong_code_root_scan_time(uint worker_i, double ms) {
204 _last_strong_code_root_scan_times_ms.set(worker_i, ms);
205 }
207 void record_obj_copy_time(uint worker_i, double ms) {
208 _last_obj_copy_times_ms.set(worker_i, ms);
209 }
211 void add_obj_copy_time(uint worker_i, double ms) {
212 _last_obj_copy_times_ms.add(worker_i, ms);
213 }
215 void record_termination(uint worker_i, double ms, size_t attempts) {
216 _last_termination_times_ms.set(worker_i, ms);
217 _last_termination_attempts.set(worker_i, attempts);
218 }
220 void record_gc_worker_end_time(uint worker_i, double ms) {
221 _last_gc_worker_end_times_ms.set(worker_i, ms);
222 }
224 void record_clear_ct_time(double ms) {
225 _cur_clear_ct_time_ms = ms;
226 }
228 void record_par_time(double ms) {
229 _cur_collection_par_time_ms = ms;
230 }
232 void record_code_root_fixup_time(double ms) {
233 _cur_collection_code_root_fixup_time_ms = ms;
234 }
236 void record_strong_code_root_migration_time(double ms) {
237 _cur_strong_code_root_migration_time_ms = ms;
238 }
240 void record_strong_code_root_purge_time(double ms) {
241 _cur_strong_code_root_purge_time_ms = ms;
242 }
244 void record_evac_fail_recalc_used_time(double ms) {
245 _cur_evac_fail_recalc_used = ms;
246 }
248 void record_evac_fail_restore_remsets(double ms) {
249 _cur_evac_fail_restore_remsets = ms;
250 }
252 void record_evac_fail_remove_self_forwards(double ms) {
253 _cur_evac_fail_remove_self_forwards = ms;
254 }
256 void note_string_dedup_fixup_start();
257 void note_string_dedup_fixup_end();
259 void record_string_dedup_fixup_time(double ms) {
260 _cur_string_dedup_fixup_time_ms = ms;
261 }
263 void record_string_dedup_queue_fixup_worker_time(uint worker_id, double ms) {
264 _cur_string_dedup_queue_fixup_worker_times_ms.set(worker_id, ms);
265 }
267 void record_string_dedup_table_fixup_worker_time(uint worker_id, double ms) {
268 _cur_string_dedup_table_fixup_worker_times_ms.set(worker_id, ms);
269 }
271 void record_ref_proc_time(double ms) {
272 _cur_ref_proc_time_ms = ms;
273 }
275 void record_ref_enq_time(double ms) {
276 _cur_ref_enq_time_ms = ms;
277 }
279 void record_root_region_scan_wait_time(double time_ms) {
280 _root_region_scan_wait_time_ms = time_ms;
281 }
283 void record_young_free_cset_time_ms(double time_ms) {
284 _recorded_young_free_cset_time_ms = time_ms;
285 }
287 void record_non_young_free_cset_time_ms(double time_ms) {
288 _recorded_non_young_free_cset_time_ms = time_ms;
289 }
291 void record_fast_reclaim_humongous_stats(size_t total, size_t candidates) {
292 _cur_fast_reclaim_humongous_total = total;
293 _cur_fast_reclaim_humongous_candidates = candidates;
294 }
296 void record_fast_reclaim_humongous_time_ms(double value, size_t reclaimed) {
297 _cur_fast_reclaim_humongous_time_ms = value;
298 _cur_fast_reclaim_humongous_reclaimed = reclaimed;
299 }
301 void record_young_cset_choice_time_ms(double time_ms) {
302 _recorded_young_cset_choice_time_ms = time_ms;
303 }
305 void record_non_young_cset_choice_time_ms(double time_ms) {
306 _recorded_non_young_cset_choice_time_ms = time_ms;
307 }
309 void record_redirty_logged_cards_time_ms(uint worker_i, double time_ms) {
310 _last_redirty_logged_cards_time_ms.set(worker_i, time_ms);
311 }
313 void record_redirty_logged_cards_processed_cards(uint worker_i, size_t processed_buffers) {
314 _last_redirty_logged_cards_processed_cards.set(worker_i, processed_buffers);
315 }
317 void record_redirty_logged_cards_time_ms(double time_ms) {
318 _recorded_redirty_logged_cards_time_ms = time_ms;
319 }
321 void record_cur_collection_start_sec(double time_ms) {
322 _cur_collection_start_sec = time_ms;
323 }
325 void record_verify_before_time_ms(double time_ms) {
326 _cur_verify_before_time_ms = time_ms;
327 }
329 void record_verify_after_time_ms(double time_ms) {
330 _cur_verify_after_time_ms = time_ms;
331 }
333 double accounted_time_ms();
335 double cur_collection_start_sec() {
336 return _cur_collection_start_sec;
337 }
339 double cur_collection_par_time_ms() {
340 return _cur_collection_par_time_ms;
341 }
343 double cur_clear_ct_time_ms() {
344 return _cur_clear_ct_time_ms;
345 }
347 double root_region_scan_wait_time_ms() {
348 return _root_region_scan_wait_time_ms;
349 }
351 double young_cset_choice_time_ms() {
352 return _recorded_young_cset_choice_time_ms;
353 }
355 double young_free_cset_time_ms() {
356 return _recorded_young_free_cset_time_ms;
357 }
359 double non_young_cset_choice_time_ms() {
360 return _recorded_non_young_cset_choice_time_ms;
361 }
363 double non_young_free_cset_time_ms() {
364 return _recorded_non_young_free_cset_time_ms;
365 }
367 double fast_reclaim_humongous_time_ms() {
368 return _cur_fast_reclaim_humongous_time_ms;
369 }
371 double average_last_update_rs_time() {
372 return _last_update_rs_times_ms.average();
373 }
375 int sum_last_update_rs_processed_buffers() {
376 return _last_update_rs_processed_buffers.sum();
377 }
379 double average_last_scan_rs_time(){
380 return _last_scan_rs_times_ms.average();
381 }
383 double average_last_strong_code_root_scan_time(){
384 return _last_strong_code_root_scan_times_ms.average();
385 }
387 double average_last_obj_copy_time() {
388 return _last_obj_copy_times_ms.average();
389 }
391 double average_last_termination_time() {
392 return _last_termination_times_ms.average();
393 }
395 double average_last_ext_root_scan_time() {
396 return _last_ext_root_scan_times_ms.average();
397 }
399 double average_last_satb_filtering_times_ms() {
400 return _last_satb_filtering_times_ms.average();
401 }
402 };
404 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP