Fri, 10 Oct 2014 15:51:58 +0200
8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso
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_purge_time_ms;
134 double _cur_evac_fail_recalc_used;
135 double _cur_evac_fail_restore_remsets;
136 double _cur_evac_fail_remove_self_forwards;
138 double _cur_string_dedup_fixup_time_ms;
139 WorkerDataArray<double> _cur_string_dedup_queue_fixup_worker_times_ms;
140 WorkerDataArray<double> _cur_string_dedup_table_fixup_worker_times_ms;
142 double _cur_clear_ct_time_ms;
143 double _cur_ref_proc_time_ms;
144 double _cur_ref_enq_time_ms;
146 double _cur_collection_start_sec;
147 double _root_region_scan_wait_time_ms;
149 double _recorded_young_cset_choice_time_ms;
150 double _recorded_non_young_cset_choice_time_ms;
152 WorkerDataArray<double> _last_redirty_logged_cards_time_ms;
153 WorkerDataArray<size_t> _last_redirty_logged_cards_processed_cards;
154 double _recorded_redirty_logged_cards_time_ms;
156 double _recorded_young_free_cset_time_ms;
157 double _recorded_non_young_free_cset_time_ms;
159 double _cur_fast_reclaim_humongous_time_ms;
160 size_t _cur_fast_reclaim_humongous_total;
161 size_t _cur_fast_reclaim_humongous_candidates;
162 size_t _cur_fast_reclaim_humongous_reclaimed;
164 double _cur_verify_before_time_ms;
165 double _cur_verify_after_time_ms;
167 // Helper methods for detailed logging
168 void print_stats(int level, const char* str, double value);
169 void print_stats(int level, const char* str, size_t value);
170 void print_stats(int level, const char* str, double value, uint workers);
172 public:
173 G1GCPhaseTimes(uint max_gc_threads);
174 void note_gc_start(uint active_gc_threads);
175 void note_gc_end();
176 void print(double pause_time_sec);
178 void record_gc_worker_start_time(uint worker_i, double ms) {
179 _last_gc_worker_start_times_ms.set(worker_i, ms);
180 }
182 void record_ext_root_scan_time(uint worker_i, double ms) {
183 _last_ext_root_scan_times_ms.set(worker_i, ms);
184 }
186 void record_satb_filtering_time(uint worker_i, double ms) {
187 _last_satb_filtering_times_ms.set(worker_i, ms);
188 }
190 void record_update_rs_time(uint worker_i, double ms) {
191 _last_update_rs_times_ms.set(worker_i, ms);
192 }
194 void record_update_rs_processed_buffers(uint worker_i, int processed_buffers) {
195 _last_update_rs_processed_buffers.set(worker_i, processed_buffers);
196 }
198 void record_scan_rs_time(uint worker_i, double ms) {
199 _last_scan_rs_times_ms.set(worker_i, ms);
200 }
202 void record_strong_code_root_scan_time(uint worker_i, double ms) {
203 _last_strong_code_root_scan_times_ms.set(worker_i, ms);
204 }
206 void record_obj_copy_time(uint worker_i, double ms) {
207 _last_obj_copy_times_ms.set(worker_i, ms);
208 }
210 void add_obj_copy_time(uint worker_i, double ms) {
211 _last_obj_copy_times_ms.add(worker_i, ms);
212 }
214 void record_termination(uint worker_i, double ms, size_t attempts) {
215 _last_termination_times_ms.set(worker_i, ms);
216 _last_termination_attempts.set(worker_i, attempts);
217 }
219 void record_gc_worker_end_time(uint worker_i, double ms) {
220 _last_gc_worker_end_times_ms.set(worker_i, ms);
221 }
223 void record_clear_ct_time(double ms) {
224 _cur_clear_ct_time_ms = ms;
225 }
227 void record_par_time(double ms) {
228 _cur_collection_par_time_ms = ms;
229 }
231 void record_code_root_fixup_time(double ms) {
232 _cur_collection_code_root_fixup_time_ms = ms;
233 }
235 void record_strong_code_root_purge_time(double ms) {
236 _cur_strong_code_root_purge_time_ms = ms;
237 }
239 void record_evac_fail_recalc_used_time(double ms) {
240 _cur_evac_fail_recalc_used = ms;
241 }
243 void record_evac_fail_restore_remsets(double ms) {
244 _cur_evac_fail_restore_remsets = ms;
245 }
247 void record_evac_fail_remove_self_forwards(double ms) {
248 _cur_evac_fail_remove_self_forwards = ms;
249 }
251 void note_string_dedup_fixup_start();
252 void note_string_dedup_fixup_end();
254 void record_string_dedup_fixup_time(double ms) {
255 _cur_string_dedup_fixup_time_ms = ms;
256 }
258 void record_string_dedup_queue_fixup_worker_time(uint worker_id, double ms) {
259 _cur_string_dedup_queue_fixup_worker_times_ms.set(worker_id, ms);
260 }
262 void record_string_dedup_table_fixup_worker_time(uint worker_id, double ms) {
263 _cur_string_dedup_table_fixup_worker_times_ms.set(worker_id, ms);
264 }
266 void record_ref_proc_time(double ms) {
267 _cur_ref_proc_time_ms = ms;
268 }
270 void record_ref_enq_time(double ms) {
271 _cur_ref_enq_time_ms = ms;
272 }
274 void record_root_region_scan_wait_time(double time_ms) {
275 _root_region_scan_wait_time_ms = time_ms;
276 }
278 void record_young_free_cset_time_ms(double time_ms) {
279 _recorded_young_free_cset_time_ms = time_ms;
280 }
282 void record_non_young_free_cset_time_ms(double time_ms) {
283 _recorded_non_young_free_cset_time_ms = time_ms;
284 }
286 void record_fast_reclaim_humongous_stats(size_t total, size_t candidates) {
287 _cur_fast_reclaim_humongous_total = total;
288 _cur_fast_reclaim_humongous_candidates = candidates;
289 }
291 void record_fast_reclaim_humongous_time_ms(double value, size_t reclaimed) {
292 _cur_fast_reclaim_humongous_time_ms = value;
293 _cur_fast_reclaim_humongous_reclaimed = reclaimed;
294 }
296 void record_young_cset_choice_time_ms(double time_ms) {
297 _recorded_young_cset_choice_time_ms = time_ms;
298 }
300 void record_non_young_cset_choice_time_ms(double time_ms) {
301 _recorded_non_young_cset_choice_time_ms = time_ms;
302 }
304 void record_redirty_logged_cards_time_ms(uint worker_i, double time_ms) {
305 _last_redirty_logged_cards_time_ms.set(worker_i, time_ms);
306 }
308 void record_redirty_logged_cards_processed_cards(uint worker_i, size_t processed_buffers) {
309 _last_redirty_logged_cards_processed_cards.set(worker_i, processed_buffers);
310 }
312 void record_redirty_logged_cards_time_ms(double time_ms) {
313 _recorded_redirty_logged_cards_time_ms = time_ms;
314 }
316 void record_cur_collection_start_sec(double time_ms) {
317 _cur_collection_start_sec = time_ms;
318 }
320 void record_verify_before_time_ms(double time_ms) {
321 _cur_verify_before_time_ms = time_ms;
322 }
324 void record_verify_after_time_ms(double time_ms) {
325 _cur_verify_after_time_ms = time_ms;
326 }
328 double accounted_time_ms();
330 double cur_collection_start_sec() {
331 return _cur_collection_start_sec;
332 }
334 double cur_collection_par_time_ms() {
335 return _cur_collection_par_time_ms;
336 }
338 double cur_clear_ct_time_ms() {
339 return _cur_clear_ct_time_ms;
340 }
342 double root_region_scan_wait_time_ms() {
343 return _root_region_scan_wait_time_ms;
344 }
346 double young_cset_choice_time_ms() {
347 return _recorded_young_cset_choice_time_ms;
348 }
350 double young_free_cset_time_ms() {
351 return _recorded_young_free_cset_time_ms;
352 }
354 double non_young_cset_choice_time_ms() {
355 return _recorded_non_young_cset_choice_time_ms;
356 }
358 double non_young_free_cset_time_ms() {
359 return _recorded_non_young_free_cset_time_ms;
360 }
362 double fast_reclaim_humongous_time_ms() {
363 return _cur_fast_reclaim_humongous_time_ms;
364 }
366 double average_last_update_rs_time() {
367 return _last_update_rs_times_ms.average();
368 }
370 int sum_last_update_rs_processed_buffers() {
371 return _last_update_rs_processed_buffers.sum();
372 }
374 double average_last_scan_rs_time(){
375 return _last_scan_rs_times_ms.average();
376 }
378 double average_last_strong_code_root_scan_time(){
379 return _last_strong_code_root_scan_times_ms.average();
380 }
382 double average_last_obj_copy_time() {
383 return _last_obj_copy_times_ms.average();
384 }
386 double average_last_termination_time() {
387 return _last_termination_times_ms.average();
388 }
390 double average_last_ext_root_scan_time() {
391 return _last_ext_root_scan_times_ms.average();
392 }
394 double average_last_satb_filtering_times_ms() {
395 return _last_satb_filtering_times_ms.average();
396 }
397 };
399 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP