1 /* 2 * Copyright (c) 2001, 2010, 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 #include "incls/_precompiled.incl" 26 #include "incls/_survRateGroup.cpp.incl" 27 28 SurvRateGroup::SurvRateGroup(G1CollectorPolicy* g1p, 29 const char* name, 30 size_t summary_surv_rates_len) : 31 _g1p(g1p), _name(name), 32 _summary_surv_rates_len(summary_surv_rates_len), 33 _summary_surv_rates_max_len(0), 34 _summary_surv_rates(NULL), 35 _surv_rate(NULL), 36 _accum_surv_rate_pred(NULL), 37 _surv_rate_pred(NULL) 38 { 39 reset(); 40 if (summary_surv_rates_len > 0) { 41 size_t length = summary_surv_rates_len; 42 _summary_surv_rates = NEW_C_HEAP_ARRAY(NumberSeq*, length); 43 if (_summary_surv_rates == NULL) { 44 vm_exit_out_of_memory(sizeof(NumberSeq*) * length, 45 "Not enough space for surv rate summary"); 46 } 47 for (size_t i = 0; i < length; ++i) 48 _summary_surv_rates[i] = new NumberSeq(); 49 } 50 51 start_adding_regions(); 52 } 53 54 55 void SurvRateGroup::reset() 56 { 57 _all_regions_allocated = 0; 58 _setup_seq_num = 0; 59 _stats_arrays_length = 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; 64 stop_adding_regions(); 65 guarantee( _stats_arrays_length == 1, "invariant" ); 66 guarantee( _surv_rate_pred[0] != NULL, "invariant" ); 67 _surv_rate_pred[0]->add(0.4); 68 all_surviving_words_recorded(false); 69 _region_num = 0; 70 } 71 72 73 void 74 SurvRateGroup::start_adding_regions() { 75 _setup_seq_num = _stats_arrays_length; 76 _region_num = 0; 77 _accum_surv_rate = 0.0; 78 79 #if 0 80 gclog_or_tty->print_cr("[%s] start adding regions, seq num %d, length %d", 81 _name, _setup_seq_num, _region_num); 82 #endif // 0 83 } 84 85 void 86 SurvRateGroup::stop_adding_regions() { 87 88 #if 0 89 gclog_or_tty->print_cr("[%s] stop adding regions, length %d", _name, _region_num); 90 #endif // 0 91 92 if (_region_num > _stats_arrays_length) { 93 double* old_surv_rate = _surv_rate; 94 double* old_accum_surv_rate_pred = _accum_surv_rate_pred; 95 TruncatedSeq** old_surv_rate_pred = _surv_rate_pred; 96 97 _surv_rate = NEW_C_HEAP_ARRAY(double, _region_num); 98 if (_surv_rate == NULL) { 99 vm_exit_out_of_memory(sizeof(double) * _region_num, 100 "Not enough space for surv rate array."); 101 } 102 _accum_surv_rate_pred = NEW_C_HEAP_ARRAY(double, _region_num); 103 if (_accum_surv_rate_pred == NULL) { 104 vm_exit_out_of_memory(sizeof(double) * _region_num, 105 "Not enough space for accum surv rate pred array."); 106 } 107 _surv_rate_pred = NEW_C_HEAP_ARRAY(TruncatedSeq*, _region_num); 108 if (_surv_rate == NULL) { 109 vm_exit_out_of_memory(sizeof(TruncatedSeq*) * _region_num, 110 "Not enough space for surv rate pred array."); 111 } 112 113 for (size_t i = 0; i < _stats_arrays_length; ++i) 114 _surv_rate_pred[i] = old_surv_rate_pred[i]; 115 116 #if 0 117 gclog_or_tty->print_cr("[%s] stop adding regions, new seqs %d to %d", 118 _name, _array_length, _region_num - 1); 119 #endif // 0 120 121 for (size_t i = _stats_arrays_length; i < _region_num; ++i) { 122 _surv_rate_pred[i] = new TruncatedSeq(10); 123 // _surv_rate_pred[i]->add(last_pred); 124 } 125 126 _stats_arrays_length = _region_num; 127 128 if (old_surv_rate != NULL) 129 FREE_C_HEAP_ARRAY(double, old_surv_rate); 130 if (old_accum_surv_rate_pred != NULL) 131 FREE_C_HEAP_ARRAY(double, old_accum_surv_rate_pred); 132 if (old_surv_rate_pred != NULL) 133 FREE_C_HEAP_ARRAY(NumberSeq*, old_surv_rate_pred); 134 } 135 136 for (size_t i = 0; i < _stats_arrays_length; ++i) 137 _surv_rate[i] = 0.0; 138 } 139 140 double 141 SurvRateGroup::accum_surv_rate(size_t adjustment) { 142 // we might relax this one in the future... 143 guarantee( adjustment == 0 || adjustment == 1, "pre-condition" ); 144 145 double ret = _accum_surv_rate; 146 if (adjustment > 0) { 147 TruncatedSeq* seq = get_seq(_region_num+1); 148 double surv_rate = _g1p->get_new_prediction(seq); 149 ret += surv_rate; 150 } 151 152 return ret; 153 } 154 155 int 156 SurvRateGroup::next_age_index() { 157 TruncatedSeq* seq = get_seq(_region_num); 158 double surv_rate = _g1p->get_new_prediction(seq); 159 _accum_surv_rate += surv_rate; 160 161 ++_region_num; 162 return (int) ++_all_regions_allocated; 163 } 164 165 void 166 SurvRateGroup::record_surviving_words(int age_in_group, size_t surv_words) { 167 guarantee( 0 <= age_in_group && (size_t) age_in_group < _region_num, 168 "pre-condition" ); 169 guarantee( _surv_rate[age_in_group] <= 0.00001, 170 "should only update each slot once" ); 171 172 double surv_rate = (double) surv_words / (double) HeapRegion::GrainWords; 173 _surv_rate[age_in_group] = surv_rate; 174 _surv_rate_pred[age_in_group]->add(surv_rate); 175 if ((size_t)age_in_group < _summary_surv_rates_len) { 176 _summary_surv_rates[age_in_group]->add(surv_rate); 177 if ((size_t)(age_in_group+1) > _summary_surv_rates_max_len) 178 _summary_surv_rates_max_len = age_in_group+1; 179 } 180 } 181 182 void 183 SurvRateGroup::all_surviving_words_recorded(bool propagate) { 184 if (propagate && _region_num > 0) { // conservative 185 double surv_rate = _surv_rate_pred[_region_num-1]->last(); 186 187 #if 0 188 gclog_or_tty->print_cr("propagating %1.2lf from %d to %d", 189 surv_rate, _curr_length, _array_length - 1); 190 #endif // 0 191 192 for (size_t i = _region_num; i < _stats_arrays_length; ++i) { 193 guarantee( _surv_rate[i] <= 0.00001, 194 "the slot should not have been updated" ); 195 _surv_rate_pred[i]->add(surv_rate); 196 } 197 } 198 199 double accum = 0.0; 200 double pred = 0.0; 201 for (size_t i = 0; i < _stats_arrays_length; ++i) { 202 pred = _g1p->get_new_prediction(_surv_rate_pred[i]); 203 if (pred > 1.0) pred = 1.0; 204 accum += pred; 205 _accum_surv_rate_pred[i] = accum; 206 // gclog_or_tty->print_cr("age %3d, accum %10.2lf", i, accum); 207 } 208 _last_pred = pred; 209 } 210 211 #ifndef PRODUCT 212 void 213 SurvRateGroup::print() { 214 gclog_or_tty->print_cr("Surv Rate Group: %s (%d entries)", 215 _name, _region_num); 216 for (size_t i = 0; i < _region_num; ++i) { 217 gclog_or_tty->print_cr(" age %4d surv rate %6.2lf %% pred %6.2lf %%", 218 i, _surv_rate[i] * 100.0, 219 _g1p->get_new_prediction(_surv_rate_pred[i]) * 100.0); 220 } 221 } 222 223 void 224 SurvRateGroup::print_surv_rate_summary() { 225 size_t length = _summary_surv_rates_max_len; 226 if (length == 0) 227 return; 228 229 gclog_or_tty->print_cr(""); 230 gclog_or_tty->print_cr("%s Rate Summary (for up to age %d)", _name, length-1); 231 gclog_or_tty->print_cr(" age range survival rate (avg) samples (avg)"); 232 gclog_or_tty->print_cr(" ---------------------------------------------------------"); 233 234 size_t index = 0; 235 size_t limit = MIN2((int) length, 10); 236 while (index < limit) { 237 gclog_or_tty->print_cr(" %4d %6.2lf%% %6.2lf", 238 index, _summary_surv_rates[index]->avg() * 100.0, 239 (double) _summary_surv_rates[index]->num()); 240 ++index; 241 } 242 243 gclog_or_tty->print_cr(" ---------------------------------------------------------"); 244 245 int num = 0; 246 double sum = 0.0; 247 int samples = 0; 248 while (index < length) { 249 ++num; 250 sum += _summary_surv_rates[index]->avg() * 100.0; 251 samples += _summary_surv_rates[index]->num(); 252 ++index; 253 254 if (index == length || num % 10 == 0) { 255 gclog_or_tty->print_cr(" %4d .. %4d %6.2lf%% %6.2lf", 256 (index-1) / 10 * 10, index-1, sum / (double) num, 257 (double) samples / (double) num); 258 sum = 0.0; 259 num = 0; 260 samples = 0; 261 } 262 } 263 264 gclog_or_tty->print_cr(" ---------------------------------------------------------"); 265 } 266 #endif // PRODUCT