src/share/vm/gc_implementation/g1/g1MonitoringSupport.cpp

Tue, 21 Aug 2012 14:10:39 -0700

author
johnc
date
Tue, 21 Aug 2012 14:10:39 -0700
changeset 3998
7383557659bd
parent 3713
720b6a76dd9d
child 4037
da91efe96a93
permissions
-rw-r--r--

7185699: G1: Prediction model discrepancies
Summary: Correct the result value of G1CollectedHeap::pending_card_num(). Change the code that calculates the GC efficiency of a non-young heap region to use historical data from mixed GCs and the actual number of live bytes when predicting how long it would take to collect the region. Changes were also reviewed by Thomas Schatzl.
Reviewed-by: azeemj, brutisso

     1 /*
     2  * Copyright (c) 2011, 2012, 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/g1MonitoringSupport.hpp"
    27 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
    28 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
    30 G1GenerationCounters::G1GenerationCounters(G1MonitoringSupport* g1mm,
    31                                            const char* name,
    32                                            int ordinal, int spaces,
    33                                            size_t min_capacity,
    34                                            size_t max_capacity,
    35                                            size_t curr_capacity)
    36   : GenerationCounters(name, ordinal, spaces, min_capacity,
    37                        max_capacity, curr_capacity), _g1mm(g1mm) { }
    39 // We pad the capacity three times given that the young generation
    40 // contains three spaces (eden and two survivors).
    41 G1YoungGenerationCounters::G1YoungGenerationCounters(G1MonitoringSupport* g1mm,
    42                                                      const char* name)
    43   : G1GenerationCounters(g1mm, name, 0 /* ordinal */, 3 /* spaces */,
    44                G1MonitoringSupport::pad_capacity(0, 3) /* min_capacity */,
    45                G1MonitoringSupport::pad_capacity(g1mm->young_gen_max(), 3),
    46                G1MonitoringSupport::pad_capacity(0, 3) /* curr_capacity */) {
    47   if (UsePerfData) {
    48     update_all();
    49   }
    50 }
    52 G1OldGenerationCounters::G1OldGenerationCounters(G1MonitoringSupport* g1mm,
    53                                                  const char* name)
    54   : G1GenerationCounters(g1mm, name, 1 /* ordinal */, 1 /* spaces */,
    55                G1MonitoringSupport::pad_capacity(0) /* min_capacity */,
    56                G1MonitoringSupport::pad_capacity(g1mm->old_gen_max()),
    57                G1MonitoringSupport::pad_capacity(0) /* curr_capacity */) {
    58   if (UsePerfData) {
    59     update_all();
    60   }
    61 }
    63 void G1YoungGenerationCounters::update_all() {
    64   size_t committed =
    65             G1MonitoringSupport::pad_capacity(_g1mm->young_gen_committed(), 3);
    66   _current_size->set_value(committed);
    67 }
    69 void G1OldGenerationCounters::update_all() {
    70   size_t committed =
    71             G1MonitoringSupport::pad_capacity(_g1mm->old_gen_committed());
    72   _current_size->set_value(committed);
    73 }
    75 G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h) :
    76   _g1h(g1h),
    77   _incremental_collection_counters(NULL),
    78   _full_collection_counters(NULL),
    79   _old_collection_counters(NULL),
    80   _old_space_counters(NULL),
    81   _young_collection_counters(NULL),
    82   _eden_counters(NULL),
    83   _from_counters(NULL),
    84   _to_counters(NULL),
    86   _overall_reserved(0),
    87   _overall_committed(0),    _overall_used(0),
    88   _young_region_num(0),
    89   _young_gen_committed(0),
    90   _eden_committed(0),       _eden_used(0),
    91   _survivor_committed(0),   _survivor_used(0),
    92   _old_committed(0),        _old_used(0) {
    94   _overall_reserved = g1h->max_capacity();
    95   recalculate_sizes();
    97   // Counters for GC collections
    98   //
    99   //  name "collector.0".  In a generational collector this would be the
   100   // young generation collection.
   101   _incremental_collection_counters =
   102     new CollectorCounters("G1 incremental collections", 0);
   103   //   name "collector.1".  In a generational collector this would be the
   104   // old generation collection.
   105   _full_collection_counters =
   106     new CollectorCounters("G1 stop-the-world full collections", 1);
   108   // timer sampling for all counters supporting sampling only update the
   109   // used value.  See the take_sample() method.  G1 requires both used and
   110   // capacity updated so sampling is not currently used.  It might
   111   // be sufficient to update all counters in take_sample() even though
   112   // take_sample() only returns "used".  When sampling was used, there
   113   // were some anomolous values emitted which may have been the consequence
   114   // of not updating all values simultaneously (i.e., see the calculation done
   115   // in eden_space_used(), is it possbile that the values used to
   116   // calculate either eden_used or survivor_used are being updated by
   117   // the collector when the sample is being done?).
   118   const bool sampled = false;
   120   // "Generation" and "Space" counters.
   121   //
   122   //  name "generation.1" This is logically the old generation in
   123   // generational GC terms.  The "1, 1" parameters are for
   124   // the n-th generation (=1) with 1 space.
   125   // Counters are created from minCapacity, maxCapacity, and capacity
   126   _old_collection_counters = new G1OldGenerationCounters(this, "old");
   128   //  name  "generation.1.space.0"
   129   // Counters are created from maxCapacity, capacity, initCapacity,
   130   // and used.
   131   _old_space_counters = new HSpaceCounters("space", 0 /* ordinal */,
   132     pad_capacity(overall_reserved()) /* max_capacity */,
   133     pad_capacity(old_space_committed()) /* init_capacity */,
   134    _old_collection_counters);
   136   //   Young collection set
   137   //  name "generation.0".  This is logically the young generation.
   138   //  The "0, 3" are paremeters for the n-th genertaion (=0) with 3 spaces.
   139   // See  _old_collection_counters for additional counters
   140   _young_collection_counters = new G1YoungGenerationCounters(this, "young");
   142   //  name "generation.0.space.0"
   143   // See _old_space_counters for additional counters
   144   _eden_counters = new HSpaceCounters("eden", 0 /* ordinal */,
   145     pad_capacity(overall_reserved()) /* max_capacity */,
   146     pad_capacity(eden_space_committed()) /* init_capacity */,
   147     _young_collection_counters);
   149   //  name "generation.0.space.1"
   150   // See _old_space_counters for additional counters
   151   // Set the arguments to indicate that this survivor space is not used.
   152   _from_counters = new HSpaceCounters("s0", 1 /* ordinal */,
   153     pad_capacity(0) /* max_capacity */,
   154     pad_capacity(0) /* init_capacity */,
   155     _young_collection_counters);
   157   //  name "generation.0.space.2"
   158   // See _old_space_counters for additional counters
   159   _to_counters = new HSpaceCounters("s1", 2 /* ordinal */,
   160     pad_capacity(overall_reserved()) /* max_capacity */,
   161     pad_capacity(survivor_space_committed()) /* init_capacity */,
   162     _young_collection_counters);
   164   if (UsePerfData) {
   165     // Given that this survivor space is not used, we update it here
   166     // once to reflect that its used space is 0 so that we don't have to
   167     // worry about updating it again later.
   168     _from_counters->update_used(0);
   169   }
   170 }
   172 void G1MonitoringSupport::recalculate_sizes() {
   173   G1CollectedHeap* g1 = g1h();
   175   // Recalculate all the sizes from scratch. We assume that this is
   176   // called at a point where no concurrent updates to the various
   177   // values we read here are possible (i.e., at a STW phase at the end
   178   // of a GC).
   180   uint young_list_length = g1->young_list()->length();
   181   uint survivor_list_length = g1->g1_policy()->recorded_survivor_regions();
   182   assert(young_list_length >= survivor_list_length, "invariant");
   183   uint eden_list_length = young_list_length - survivor_list_length;
   184   // Max length includes any potential extensions to the young gen
   185   // we'll do when the GC locker is active.
   186   uint young_list_max_length = g1->g1_policy()->young_list_max_length();
   187   assert(young_list_max_length >= survivor_list_length, "invariant");
   188   uint eden_list_max_length = young_list_max_length - survivor_list_length;
   190   _overall_used = g1->used_unlocked();
   191   _eden_used = (size_t) eden_list_length * HeapRegion::GrainBytes;
   192   _survivor_used = (size_t) survivor_list_length * HeapRegion::GrainBytes;
   193   _young_region_num = young_list_length;
   194   _old_used = subtract_up_to_zero(_overall_used, _eden_used + _survivor_used);
   196   // First calculate the committed sizes that can be calculated independently.
   197   _survivor_committed = _survivor_used;
   198   _old_committed = HeapRegion::align_up_to_region_byte_size(_old_used);
   200   // Next, start with the overall committed size.
   201   _overall_committed = g1->capacity();
   202   size_t committed = _overall_committed;
   204   // Remove the committed size we have calculated so far (for the
   205   // survivor and old space).
   206   assert(committed >= (_survivor_committed + _old_committed), "sanity");
   207   committed -= _survivor_committed + _old_committed;
   209   // Next, calculate and remove the committed size for the eden.
   210   _eden_committed = (size_t) eden_list_max_length * HeapRegion::GrainBytes;
   211   // Somewhat defensive: be robust in case there are inaccuracies in
   212   // the calculations
   213   _eden_committed = MIN2(_eden_committed, committed);
   214   committed -= _eden_committed;
   216   // Finally, give the rest to the old space...
   217   _old_committed += committed;
   218   // ..and calculate the young gen committed.
   219   _young_gen_committed = _eden_committed + _survivor_committed;
   221   assert(_overall_committed ==
   222          (_eden_committed + _survivor_committed + _old_committed),
   223          "the committed sizes should add up");
   224   // Somewhat defensive: cap the eden used size to make sure it
   225   // never exceeds the committed size.
   226   _eden_used = MIN2(_eden_used, _eden_committed);
   227   // _survivor_committed and _old_committed are calculated in terms of
   228   // the corresponding _*_used value, so the next two conditions
   229   // should hold.
   230   assert(_survivor_used <= _survivor_committed, "post-condition");
   231   assert(_old_used <= _old_committed, "post-condition");
   232 }
   234 void G1MonitoringSupport::recalculate_eden_size() {
   235   G1CollectedHeap* g1 = g1h();
   237   // When a new eden region is allocated, only the eden_used size is
   238   // affected (since we have recalculated everything else at the last GC).
   240   uint young_region_num = g1h()->young_list()->length();
   241   if (young_region_num > _young_region_num) {
   242     uint diff = young_region_num - _young_region_num;
   243     _eden_used += (size_t) diff * HeapRegion::GrainBytes;
   244     // Somewhat defensive: cap the eden used size to make sure it
   245     // never exceeds the committed size.
   246     _eden_used = MIN2(_eden_used, _eden_committed);
   247     _young_region_num = young_region_num;
   248   }
   249 }
   251 void G1MonitoringSupport::update_sizes() {
   252   recalculate_sizes();
   253   if (UsePerfData) {
   254     eden_counters()->update_capacity(pad_capacity(eden_space_committed()));
   255     eden_counters()->update_used(eden_space_used());
   256     // only the to survivor space (s1) is active, so we don't need to
   257     // update the counteres for the from survivor space (s0)
   258     to_counters()->update_capacity(pad_capacity(survivor_space_committed()));
   259     to_counters()->update_used(survivor_space_used());
   260     old_space_counters()->update_capacity(pad_capacity(old_space_committed()));
   261     old_space_counters()->update_used(old_space_used());
   262     old_collection_counters()->update_all();
   263     young_collection_counters()->update_all();
   264   }
   265 }
   267 void G1MonitoringSupport::update_eden_size() {
   268   recalculate_eden_size();
   269   if (UsePerfData) {
   270     eden_counters()->update_used(eden_space_used());
   271   }
   272 }

mercurial