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) 2001, 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 #include "precompiled.hpp"
26 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
27 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
28 #include "gc_implementation/g1/heapRegion.hpp"
29 #include "gc_implementation/g1/survRateGroup.hpp"
30 #include "memory/allocation.hpp"
32 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
34 SurvRateGroup::SurvRateGroup(G1CollectorPolicy* g1p,
35 const char* name,
36 size_t summary_surv_rates_len) :
37 _g1p(g1p), _name(name),
38 _summary_surv_rates_len(summary_surv_rates_len),
39 _summary_surv_rates_max_len(0),
40 _summary_surv_rates(NULL),
41 _surv_rate(NULL),
42 _accum_surv_rate_pred(NULL),
43 _surv_rate_pred(NULL),
44 _stats_arrays_length(0) {
45 reset();
46 if (summary_surv_rates_len > 0) {
47 size_t length = summary_surv_rates_len;
48 _summary_surv_rates = NEW_C_HEAP_ARRAY(NumberSeq*, length, mtGC);
49 for (size_t i = 0; i < length; ++i) {
50 _summary_surv_rates[i] = new NumberSeq();
51 }
52 }
54 start_adding_regions();
55 }
57 void SurvRateGroup::reset() {
58 _all_regions_allocated = 0;
59 _setup_seq_num = 0;
60 _accum_surv_rate = 0.0;
61 _last_pred = 0.0;
62 // the following will set up the arrays with length 1
63 _region_num = 1;
65 // The call to stop_adding_regions() will use "new" to refill
66 // the _surv_rate_pred array, so we need to make sure to call
67 // "delete".
68 for (size_t i = 0; i < _stats_arrays_length; ++i) {
69 delete _surv_rate_pred[i];
70 }
71 _stats_arrays_length = 0;
73 stop_adding_regions();
74 guarantee( _stats_arrays_length == 1, "invariant" );
75 guarantee( _surv_rate_pred[0] != NULL, "invariant" );
76 _surv_rate_pred[0]->add(0.4);
77 all_surviving_words_recorded(false);
78 _region_num = 0;
79 }
81 void
82 SurvRateGroup::start_adding_regions() {
83 _setup_seq_num = _stats_arrays_length;
84 _region_num = 0;
85 _accum_surv_rate = 0.0;
86 }
88 void
89 SurvRateGroup::stop_adding_regions() {
90 if (_region_num > _stats_arrays_length) {
91 double* old_surv_rate = _surv_rate;
92 double* old_accum_surv_rate_pred = _accum_surv_rate_pred;
93 TruncatedSeq** old_surv_rate_pred = _surv_rate_pred;
95 _surv_rate = NEW_C_HEAP_ARRAY(double, _region_num, mtGC);
96 _accum_surv_rate_pred = NEW_C_HEAP_ARRAY(double, _region_num, mtGC);
97 _surv_rate_pred = NEW_C_HEAP_ARRAY(TruncatedSeq*, _region_num, mtGC);
99 for (size_t i = 0; i < _stats_arrays_length; ++i) {
100 _surv_rate_pred[i] = old_surv_rate_pred[i];
101 }
102 for (size_t i = _stats_arrays_length; i < _region_num; ++i) {
103 _surv_rate_pred[i] = new TruncatedSeq(10);
104 }
106 _stats_arrays_length = _region_num;
108 if (old_surv_rate != NULL) {
109 FREE_C_HEAP_ARRAY(double, old_surv_rate, mtGC);
110 }
111 if (old_accum_surv_rate_pred != NULL) {
112 FREE_C_HEAP_ARRAY(double, old_accum_surv_rate_pred, mtGC);
113 }
114 if (old_surv_rate_pred != NULL) {
115 FREE_C_HEAP_ARRAY(TruncatedSeq*, old_surv_rate_pred, mtGC);
116 }
117 }
119 for (size_t i = 0; i < _stats_arrays_length; ++i) {
120 _surv_rate[i] = 0.0;
121 }
122 }
124 double
125 SurvRateGroup::accum_surv_rate(size_t adjustment) {
126 // we might relax this one in the future...
127 guarantee( adjustment == 0 || adjustment == 1, "pre-condition" );
129 double ret = _accum_surv_rate;
130 if (adjustment > 0) {
131 TruncatedSeq* seq = get_seq(_region_num+1);
132 double surv_rate = _g1p->get_new_prediction(seq);
133 ret += surv_rate;
134 }
136 return ret;
137 }
139 int
140 SurvRateGroup::next_age_index() {
141 TruncatedSeq* seq = get_seq(_region_num);
142 double surv_rate = _g1p->get_new_prediction(seq);
143 _accum_surv_rate += surv_rate;
145 ++_region_num;
146 return (int) ++_all_regions_allocated;
147 }
149 void
150 SurvRateGroup::record_surviving_words(int age_in_group, size_t surv_words) {
151 guarantee( 0 <= age_in_group && (size_t) age_in_group < _region_num,
152 "pre-condition" );
153 guarantee( _surv_rate[age_in_group] <= 0.00001,
154 "should only update each slot once" );
156 double surv_rate = (double) surv_words / (double) HeapRegion::GrainWords;
157 _surv_rate[age_in_group] = surv_rate;
158 _surv_rate_pred[age_in_group]->add(surv_rate);
159 if ((size_t)age_in_group < _summary_surv_rates_len) {
160 _summary_surv_rates[age_in_group]->add(surv_rate);
161 if ((size_t)(age_in_group+1) > _summary_surv_rates_max_len)
162 _summary_surv_rates_max_len = age_in_group+1;
163 }
164 }
166 void
167 SurvRateGroup::all_surviving_words_recorded(bool propagate) {
168 if (propagate && _region_num > 0) { // conservative
169 double surv_rate = _surv_rate_pred[_region_num-1]->last();
170 for (size_t i = _region_num; i < _stats_arrays_length; ++i) {
171 guarantee( _surv_rate[i] <= 0.00001,
172 "the slot should not have been updated" );
173 _surv_rate_pred[i]->add(surv_rate);
174 }
175 }
177 double accum = 0.0;
178 double pred = 0.0;
179 for (size_t i = 0; i < _stats_arrays_length; ++i) {
180 pred = _g1p->get_new_prediction(_surv_rate_pred[i]);
181 if (pred > 1.0) pred = 1.0;
182 accum += pred;
183 _accum_surv_rate_pred[i] = accum;
184 // gclog_or_tty->print_cr("age %3d, accum %10.2lf", i, accum);
185 }
186 _last_pred = pred;
187 }
189 #ifndef PRODUCT
190 void
191 SurvRateGroup::print() {
192 gclog_or_tty->print_cr("Surv Rate Group: %s (%d entries)",
193 _name, _region_num);
194 for (size_t i = 0; i < _region_num; ++i) {
195 gclog_or_tty->print_cr(" age %4d surv rate %6.2lf %% pred %6.2lf %%",
196 i, _surv_rate[i] * 100.0,
197 _g1p->get_new_prediction(_surv_rate_pred[i]) * 100.0);
198 }
199 }
201 void
202 SurvRateGroup::print_surv_rate_summary() {
203 size_t length = _summary_surv_rates_max_len;
204 if (length == 0)
205 return;
207 gclog_or_tty->cr();
208 gclog_or_tty->print_cr("%s Rate Summary (for up to age %d)", _name, length-1);
209 gclog_or_tty->print_cr(" age range survival rate (avg) samples (avg)");
210 gclog_or_tty->print_cr(" ---------------------------------------------------------");
212 size_t index = 0;
213 size_t limit = MIN2((int) length, 10);
214 while (index < limit) {
215 gclog_or_tty->print_cr(" %4d %6.2lf%% %6.2lf",
216 index, _summary_surv_rates[index]->avg() * 100.0,
217 (double) _summary_surv_rates[index]->num());
218 ++index;
219 }
221 gclog_or_tty->print_cr(" ---------------------------------------------------------");
223 int num = 0;
224 double sum = 0.0;
225 int samples = 0;
226 while (index < length) {
227 ++num;
228 sum += _summary_surv_rates[index]->avg() * 100.0;
229 samples += _summary_surv_rates[index]->num();
230 ++index;
232 if (index == length || num % 10 == 0) {
233 gclog_or_tty->print_cr(" %4d .. %4d %6.2lf%% %6.2lf",
234 (index-1) / 10 * 10, index-1, sum / (double) num,
235 (double) samples / (double) num);
236 sum = 0.0;
237 num = 0;
238 samples = 0;
239 }
240 }
242 gclog_or_tty->print_cr(" ---------------------------------------------------------");
243 }
244 #endif // PRODUCT