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

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

author
johnc
date
Tue, 21 Aug 2012 14:10:39 -0700
changeset 3998
7383557659bd
parent 3900
d2a62e0f25eb
child 5237
f2110083203d
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 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1MONITORINGSUPPORT_HPP
    26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1MONITORINGSUPPORT_HPP
    28 #include "gc_implementation/shared/hSpaceCounters.hpp"
    30 class G1CollectedHeap;
    32 // Class for monitoring logical spaces in G1. It provides data for
    33 // both G1's jstat counters as well as G1's memory pools.
    34 //
    35 // G1 splits the heap into heap regions and each heap region belongs
    36 // to one of the following categories:
    37 //
    38 // * eden      : regions that have been allocated since the last GC
    39 // * survivors : regions with objects that survived the last few GCs
    40 // * old       : long-lived non-humongous regions
    41 // * humongous : humongous regions
    42 // * free      : free regions
    43 //
    44 // The combination of eden and survivor regions form the equivalent of
    45 // the young generation in the other GCs. The combination of old and
    46 // humongous regions form the equivalent of the old generation in the
    47 // other GCs. Free regions do not have a good equivalent in the other
    48 // GCs given that they can be allocated as any of the other region types.
    49 //
    50 // The monitoring tools expect the heap to contain a number of
    51 // generations (young, old, perm) and each generation to contain a
    52 // number of spaces (young: eden, survivors, old). Given that G1 does
    53 // not maintain those spaces physically (e.g., the set of
    54 // non-contiguous eden regions can be considered as a "logical"
    55 // space), we'll provide the illusion that those generations and
    56 // spaces exist. In reality, each generation and space refers to a set
    57 // of heap regions that are potentially non-contiguous.
    58 //
    59 // This class provides interfaces to access the min, current, and max
    60 // capacity and current occupancy for each of G1's logical spaces and
    61 // generations we expose to the monitoring tools. Also provided are
    62 // counters for G1 concurrent collections and stop-the-world full heap
    63 // collections.
    64 //
    65 // Below is a description of how the various sizes are calculated.
    66 //
    67 // * Current Capacity
    68 //
    69 //    - heap_capacity = current heap capacity (e.g., current committed size)
    70 //    - young_gen_capacity = current max young gen target capacity
    71 //          (i.e., young gen target capacity + max allowed expansion capacity)
    72 //    - survivor_capacity = current survivor region capacity
    73 //    - eden_capacity = young_gen_capacity - survivor_capacity
    74 //    - old_capacity = heap_capacity - young_gen_capacity
    75 //
    76 //    What we do in the above is to distribute the free regions among
    77 //    eden_capacity and old_capacity.
    78 //
    79 // * Occupancy
    80 //
    81 //    - young_gen_used = current young region capacity
    82 //    - survivor_used = survivor_capacity
    83 //    - eden_used = young_gen_used - survivor_used
    84 //    - old_used = overall_used - young_gen_used
    85 //
    86 //    Unfortunately, we currently only keep track of the number of
    87 //    currently allocated young and survivor regions + the overall used
    88 //    bytes in the heap, so the above can be a little inaccurate.
    89 //
    90 // * Min Capacity
    91 //
    92 //    We set this to 0 for all spaces.
    93 //
    94 // * Max Capacity
    95 //
    96 //    For jstat, we set the max capacity of all spaces to heap_capacity,
    97 //    given that we don't always have a reasonable upper bound on how big
    98 //    each space can grow. For the memory pools, we make the max
    99 //    capacity undefined with the exception of the old memory pool for
   100 //    which we make the max capacity same as the max heap capacity.
   101 //
   102 // If we had more accurate occupancy / capacity information per
   103 // region set the above calculations would be greatly simplified and
   104 // be made more accurate.
   105 //
   106 // We update all the above synchronously and we store the results in
   107 // fields so that we just read said fields when needed. A subtle point
   108 // is that all the above sizes need to be recalculated when the old
   109 // gen changes capacity (after a GC or after a humongous allocation)
   110 // but only the eden occupancy changes when a new eden region is
   111 // allocated. So, in the latter case we have minimal recalcuation to
   112 // do which is important as we want to keep the eden region allocation
   113 // path as low-overhead as possible.
   115 class G1MonitoringSupport : public CHeapObj<mtGC> {
   116   friend class VMStructs;
   118   G1CollectedHeap* _g1h;
   120   // jstat performance counters
   121   //  incremental collections both young and mixed
   122   CollectorCounters*   _incremental_collection_counters;
   123   //  full stop-the-world collections
   124   CollectorCounters*   _full_collection_counters;
   125   //  young collection set counters.  The _eden_counters,
   126   // _from_counters, and _to_counters are associated with
   127   // this "generational" counter.
   128   GenerationCounters*  _young_collection_counters;
   129   //  old collection set counters. The _old_space_counters
   130   // below are associated with this "generational" counter.
   131   GenerationCounters*  _old_collection_counters;
   132   // Counters for the capacity and used for
   133   //   the whole heap
   134   HSpaceCounters*      _old_space_counters;
   135   //   the young collection
   136   HSpaceCounters*      _eden_counters;
   137   //   the survivor collection (only one, _to_counters, is actively used)
   138   HSpaceCounters*      _from_counters;
   139   HSpaceCounters*      _to_counters;
   141   // When it's appropriate to recalculate the various sizes (at the
   142   // end of a GC, when a new eden region is allocated, etc.) we store
   143   // them here so that we can easily report them when needed and not
   144   // have to recalculate them every time.
   146   size_t _overall_reserved;
   147   size_t _overall_committed;
   148   size_t _overall_used;
   150   uint   _young_region_num;
   151   size_t _young_gen_committed;
   152   size_t _eden_committed;
   153   size_t _eden_used;
   154   size_t _survivor_committed;
   155   size_t _survivor_used;
   157   size_t _old_committed;
   158   size_t _old_used;
   160   G1CollectedHeap* g1h() { return _g1h; }
   162   // It returns x - y if x > y, 0 otherwise.
   163   // As described in the comment above, some of the inputs to the
   164   // calculations we have to do are obtained concurrently and hence
   165   // may be inconsistent with each other. So, this provides a
   166   // defensive way of performing the subtraction and avoids the value
   167   // going negative (which would mean a very large result, given that
   168   // the parameter are size_t).
   169   static size_t subtract_up_to_zero(size_t x, size_t y) {
   170     if (x > y) {
   171       return x - y;
   172     } else {
   173       return 0;
   174     }
   175   }
   177   // Recalculate all the sizes.
   178   void recalculate_sizes();
   179   // Recalculate only what's necessary when a new eden region is allocated.
   180   void recalculate_eden_size();
   182  public:
   183   G1MonitoringSupport(G1CollectedHeap* g1h);
   185   // Unfortunately, the jstat tool assumes that no space has 0
   186   // capacity. In our case, given that each space is logical, it's
   187   // possible that no regions will be allocated to it, hence to have 0
   188   // capacity (e.g., if there are no survivor regions, the survivor
   189   // space has 0 capacity). The way we deal with this is to always pad
   190   // each capacity value we report to jstat by a very small amount to
   191   // make sure that it's never zero. Given that we sometimes have to
   192   // report a capacity of a generation that contains several spaces
   193   // (e.g., young gen includes one eden, two survivor spaces), the
   194   // mult parameter is provided in order to adding the appropriate
   195   // padding multiple times so that the capacities add up correctly.
   196   static size_t pad_capacity(size_t size_bytes, size_t mult = 1) {
   197     return size_bytes + MinObjAlignmentInBytes * mult;
   198   }
   200   // Recalculate all the sizes from scratch and update all the jstat
   201   // counters accordingly.
   202   void update_sizes();
   203   // Recalculate only what's necessary when a new eden region is
   204   // allocated and update any jstat counters that need to be updated.
   205   void update_eden_size();
   207   CollectorCounters* incremental_collection_counters() {
   208     return _incremental_collection_counters;
   209   }
   210   CollectorCounters* full_collection_counters() {
   211     return _full_collection_counters;
   212   }
   213   GenerationCounters* young_collection_counters() {
   214     return _young_collection_counters;
   215   }
   216   GenerationCounters* old_collection_counters() {
   217     return _old_collection_counters;
   218   }
   219   HSpaceCounters*      old_space_counters() { return _old_space_counters; }
   220   HSpaceCounters*      eden_counters() { return _eden_counters; }
   221   HSpaceCounters*      from_counters() { return _from_counters; }
   222   HSpaceCounters*      to_counters() { return _to_counters; }
   224   // Monitoring support used by
   225   //   MemoryService
   226   //   jstat counters
   228   size_t overall_reserved()           { return _overall_reserved;     }
   229   size_t overall_committed()          { return _overall_committed;    }
   230   size_t overall_used()               { return _overall_used;         }
   232   size_t young_gen_committed()        { return _young_gen_committed;  }
   233   size_t young_gen_max()              { return overall_reserved();    }
   234   size_t eden_space_committed()       { return _eden_committed;       }
   235   size_t eden_space_used()            { return _eden_used;            }
   236   size_t survivor_space_committed()   { return _survivor_committed;   }
   237   size_t survivor_space_used()        { return _survivor_used;        }
   239   size_t old_gen_committed()          { return old_space_committed(); }
   240   size_t old_gen_max()                { return overall_reserved();    }
   241   size_t old_space_committed()        { return _old_committed;        }
   242   size_t old_space_used()             { return _old_used;             }
   243 };
   245 class G1GenerationCounters: public GenerationCounters {
   246 protected:
   247   G1MonitoringSupport* _g1mm;
   249 public:
   250   G1GenerationCounters(G1MonitoringSupport* g1mm,
   251                        const char* name, int ordinal, int spaces,
   252                        size_t min_capacity, size_t max_capacity,
   253                        size_t curr_capacity);
   254 };
   256 class G1YoungGenerationCounters: public G1GenerationCounters {
   257 public:
   258   G1YoungGenerationCounters(G1MonitoringSupport* g1mm, const char* name);
   259   virtual void update_all();
   260 };
   262 class G1OldGenerationCounters: public G1GenerationCounters {
   263 public:
   264   G1OldGenerationCounters(G1MonitoringSupport* g1mm, const char* name);
   265   virtual void update_all();
   266 };
   268 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1MONITORINGSUPPORT_HPP

mercurial