ysr@777: /* trims@1907: * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. ysr@777: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ysr@777: * ysr@777: * This code is free software; you can redistribute it and/or modify it ysr@777: * under the terms of the GNU General Public License version 2 only, as ysr@777: * published by the Free Software Foundation. ysr@777: * ysr@777: * This code is distributed in the hope that it will be useful, but WITHOUT ysr@777: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ysr@777: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ysr@777: * version 2 for more details (a copy is included in the LICENSE file that ysr@777: * accompanied this code). ysr@777: * ysr@777: * You should have received a copy of the GNU General Public License version ysr@777: * 2 along with this work; if not, write to the Free Software Foundation, ysr@777: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ysr@777: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. ysr@777: * ysr@777: */ ysr@777: stefank@2314: #include "precompiled.hpp" stefank@2314: #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" stefank@2314: #include "gc_implementation/g1/g1CollectorPolicy.hpp" stefank@2314: #include "gc_implementation/g1/heapRegion.hpp" stefank@2314: #include "gc_implementation/g1/survRateGroup.hpp" stefank@2314: #include "memory/allocation.hpp" ysr@777: ysr@777: SurvRateGroup::SurvRateGroup(G1CollectorPolicy* g1p, ysr@777: const char* name, ysr@777: size_t summary_surv_rates_len) : ysr@777: _g1p(g1p), _name(name), ysr@777: _summary_surv_rates_len(summary_surv_rates_len), ysr@777: _summary_surv_rates_max_len(0), apetrusenko@980: _summary_surv_rates(NULL), apetrusenko@980: _surv_rate(NULL), apetrusenko@980: _accum_surv_rate_pred(NULL), apetrusenko@980: _surv_rate_pred(NULL) apetrusenko@980: { apetrusenko@980: reset(); ysr@777: if (summary_surv_rates_len > 0) { ysr@777: size_t length = summary_surv_rates_len; ysr@777: _summary_surv_rates = NEW_C_HEAP_ARRAY(NumberSeq*, length); ysr@777: if (_summary_surv_rates == NULL) { ysr@777: vm_exit_out_of_memory(sizeof(NumberSeq*) * length, ysr@777: "Not enough space for surv rate summary"); ysr@777: } ysr@777: for (size_t i = 0; i < length; ++i) ysr@777: _summary_surv_rates[i] = new NumberSeq(); ysr@777: } ysr@777: ysr@777: start_adding_regions(); ysr@777: } ysr@777: apetrusenko@980: apetrusenko@980: void SurvRateGroup::reset() apetrusenko@980: { apetrusenko@980: _all_regions_allocated = 0; apetrusenko@980: _setup_seq_num = 0; apetrusenko@980: _stats_arrays_length = 0; apetrusenko@980: _accum_surv_rate = 0.0; apetrusenko@980: _last_pred = 0.0; apetrusenko@980: // the following will set up the arrays with length 1 apetrusenko@980: _region_num = 1; apetrusenko@980: stop_adding_regions(); apetrusenko@980: guarantee( _stats_arrays_length == 1, "invariant" ); apetrusenko@980: guarantee( _surv_rate_pred[0] != NULL, "invariant" ); apetrusenko@980: _surv_rate_pred[0]->add(0.4); apetrusenko@980: all_surviving_words_recorded(false); apetrusenko@980: _region_num = 0; apetrusenko@980: } apetrusenko@980: apetrusenko@980: ysr@777: void ysr@777: SurvRateGroup::start_adding_regions() { apetrusenko@980: _setup_seq_num = _stats_arrays_length; johnc@1829: _region_num = 0; ysr@777: _accum_surv_rate = 0.0; ysr@777: ysr@777: #if 0 apetrusenko@980: gclog_or_tty->print_cr("[%s] start adding regions, seq num %d, length %d", apetrusenko@980: _name, _setup_seq_num, _region_num); ysr@777: #endif // 0 ysr@777: } ysr@777: ysr@777: void ysr@777: SurvRateGroup::stop_adding_regions() { ysr@777: ysr@777: #if 0 apetrusenko@980: gclog_or_tty->print_cr("[%s] stop adding regions, length %d", _name, _region_num); ysr@777: #endif // 0 ysr@777: apetrusenko@980: if (_region_num > _stats_arrays_length) { ysr@777: double* old_surv_rate = _surv_rate; ysr@777: double* old_accum_surv_rate_pred = _accum_surv_rate_pred; ysr@777: TruncatedSeq** old_surv_rate_pred = _surv_rate_pred; ysr@777: apetrusenko@980: _surv_rate = NEW_C_HEAP_ARRAY(double, _region_num); ysr@777: if (_surv_rate == NULL) { apetrusenko@980: vm_exit_out_of_memory(sizeof(double) * _region_num, ysr@777: "Not enough space for surv rate array."); ysr@777: } apetrusenko@980: _accum_surv_rate_pred = NEW_C_HEAP_ARRAY(double, _region_num); ysr@777: if (_accum_surv_rate_pred == NULL) { apetrusenko@980: vm_exit_out_of_memory(sizeof(double) * _region_num, ysr@777: "Not enough space for accum surv rate pred array."); ysr@777: } apetrusenko@980: _surv_rate_pred = NEW_C_HEAP_ARRAY(TruncatedSeq*, _region_num); ysr@777: if (_surv_rate == NULL) { apetrusenko@980: vm_exit_out_of_memory(sizeof(TruncatedSeq*) * _region_num, ysr@777: "Not enough space for surv rate pred array."); ysr@777: } ysr@777: apetrusenko@980: for (size_t i = 0; i < _stats_arrays_length; ++i) ysr@777: _surv_rate_pred[i] = old_surv_rate_pred[i]; ysr@777: ysr@777: #if 0 apetrusenko@980: gclog_or_tty->print_cr("[%s] stop adding regions, new seqs %d to %d", apetrusenko@980: _name, _array_length, _region_num - 1); ysr@777: #endif // 0 ysr@777: apetrusenko@980: for (size_t i = _stats_arrays_length; i < _region_num; ++i) { ysr@777: _surv_rate_pred[i] = new TruncatedSeq(10); ysr@777: // _surv_rate_pred[i]->add(last_pred); ysr@777: } ysr@777: apetrusenko@980: _stats_arrays_length = _region_num; ysr@777: ysr@777: if (old_surv_rate != NULL) ysr@777: FREE_C_HEAP_ARRAY(double, old_surv_rate); ysr@777: if (old_accum_surv_rate_pred != NULL) ysr@777: FREE_C_HEAP_ARRAY(double, old_accum_surv_rate_pred); ysr@777: if (old_surv_rate_pred != NULL) ysr@777: FREE_C_HEAP_ARRAY(NumberSeq*, old_surv_rate_pred); ysr@777: } ysr@777: apetrusenko@980: for (size_t i = 0; i < _stats_arrays_length; ++i) ysr@777: _surv_rate[i] = 0.0; ysr@777: } ysr@777: ysr@777: double ysr@777: SurvRateGroup::accum_surv_rate(size_t adjustment) { ysr@777: // we might relax this one in the future... ysr@777: guarantee( adjustment == 0 || adjustment == 1, "pre-condition" ); ysr@777: ysr@777: double ret = _accum_surv_rate; ysr@777: if (adjustment > 0) { apetrusenko@980: TruncatedSeq* seq = get_seq(_region_num+1); ysr@777: double surv_rate = _g1p->get_new_prediction(seq); ysr@777: ret += surv_rate; ysr@777: } ysr@777: ysr@777: return ret; ysr@777: } ysr@777: ysr@777: int ysr@777: SurvRateGroup::next_age_index() { apetrusenko@980: TruncatedSeq* seq = get_seq(_region_num); ysr@777: double surv_rate = _g1p->get_new_prediction(seq); ysr@777: _accum_surv_rate += surv_rate; ysr@777: apetrusenko@980: ++_region_num; ysr@777: return (int) ++_all_regions_allocated; ysr@777: } ysr@777: ysr@777: void ysr@777: SurvRateGroup::record_surviving_words(int age_in_group, size_t surv_words) { apetrusenko@980: guarantee( 0 <= age_in_group && (size_t) age_in_group < _region_num, ysr@777: "pre-condition" ); ysr@777: guarantee( _surv_rate[age_in_group] <= 0.00001, ysr@777: "should only update each slot once" ); ysr@777: ysr@777: double surv_rate = (double) surv_words / (double) HeapRegion::GrainWords; ysr@777: _surv_rate[age_in_group] = surv_rate; ysr@777: _surv_rate_pred[age_in_group]->add(surv_rate); ysr@777: if ((size_t)age_in_group < _summary_surv_rates_len) { ysr@777: _summary_surv_rates[age_in_group]->add(surv_rate); ysr@777: if ((size_t)(age_in_group+1) > _summary_surv_rates_max_len) ysr@777: _summary_surv_rates_max_len = age_in_group+1; ysr@777: } ysr@777: } ysr@777: ysr@777: void ysr@777: SurvRateGroup::all_surviving_words_recorded(bool propagate) { apetrusenko@980: if (propagate && _region_num > 0) { // conservative apetrusenko@980: double surv_rate = _surv_rate_pred[_region_num-1]->last(); ysr@777: ysr@777: #if 0 ysr@777: gclog_or_tty->print_cr("propagating %1.2lf from %d to %d", ysr@777: surv_rate, _curr_length, _array_length - 1); ysr@777: #endif // 0 ysr@777: apetrusenko@980: for (size_t i = _region_num; i < _stats_arrays_length; ++i) { ysr@777: guarantee( _surv_rate[i] <= 0.00001, ysr@777: "the slot should not have been updated" ); ysr@777: _surv_rate_pred[i]->add(surv_rate); ysr@777: } ysr@777: } ysr@777: ysr@777: double accum = 0.0; ysr@777: double pred = 0.0; apetrusenko@980: for (size_t i = 0; i < _stats_arrays_length; ++i) { ysr@777: pred = _g1p->get_new_prediction(_surv_rate_pred[i]); ysr@777: if (pred > 1.0) pred = 1.0; ysr@777: accum += pred; ysr@777: _accum_surv_rate_pred[i] = accum; ysr@777: // gclog_or_tty->print_cr("age %3d, accum %10.2lf", i, accum); ysr@777: } ysr@777: _last_pred = pred; ysr@777: } ysr@777: ysr@777: #ifndef PRODUCT ysr@777: void ysr@777: SurvRateGroup::print() { johnc@1829: gclog_or_tty->print_cr("Surv Rate Group: %s (%d entries)", johnc@1829: _name, _region_num); apetrusenko@980: for (size_t i = 0; i < _region_num; ++i) { johnc@1829: gclog_or_tty->print_cr(" age %4d surv rate %6.2lf %% pred %6.2lf %%", ysr@777: i, _surv_rate[i] * 100.0, johnc@1829: _g1p->get_new_prediction(_surv_rate_pred[i]) * 100.0); ysr@777: } ysr@777: } ysr@777: ysr@777: void ysr@777: SurvRateGroup::print_surv_rate_summary() { ysr@777: size_t length = _summary_surv_rates_max_len; ysr@777: if (length == 0) ysr@777: return; ysr@777: ysr@777: gclog_or_tty->print_cr(""); ysr@777: gclog_or_tty->print_cr("%s Rate Summary (for up to age %d)", _name, length-1); ysr@777: gclog_or_tty->print_cr(" age range survival rate (avg) samples (avg)"); ysr@777: gclog_or_tty->print_cr(" ---------------------------------------------------------"); ysr@777: ysr@777: size_t index = 0; ysr@777: size_t limit = MIN2((int) length, 10); ysr@777: while (index < limit) { ysr@777: gclog_or_tty->print_cr(" %4d %6.2lf%% %6.2lf", ysr@777: index, _summary_surv_rates[index]->avg() * 100.0, ysr@777: (double) _summary_surv_rates[index]->num()); ysr@777: ++index; ysr@777: } ysr@777: ysr@777: gclog_or_tty->print_cr(" ---------------------------------------------------------"); ysr@777: ysr@777: int num = 0; ysr@777: double sum = 0.0; ysr@777: int samples = 0; ysr@777: while (index < length) { ysr@777: ++num; ysr@777: sum += _summary_surv_rates[index]->avg() * 100.0; ysr@777: samples += _summary_surv_rates[index]->num(); ysr@777: ++index; ysr@777: ysr@777: if (index == length || num % 10 == 0) { ysr@777: gclog_or_tty->print_cr(" %4d .. %4d %6.2lf%% %6.2lf", ysr@777: (index-1) / 10 * 10, index-1, sum / (double) num, ysr@777: (double) samples / (double) num); ysr@777: sum = 0.0; ysr@777: num = 0; ysr@777: samples = 0; ysr@777: } ysr@777: } ysr@777: ysr@777: gclog_or_tty->print_cr(" ---------------------------------------------------------"); ysr@777: } ysr@777: #endif // PRODUCT