src/share/vm/gc_implementation/shared/allocationStats.hpp

Thu, 20 Sep 2012 09:52:56 -0700

author
johnc
date
Thu, 20 Sep 2012 09:52:56 -0700
changeset 4067
b2ef234911c9
parent 3732
f69a5d43dc19
child 4153
b9a9ed0f8eeb
permissions
-rw-r--r--

7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
Summary: Reset the fields in ParGCAllocBuffer, that are used for accumulating values for the ResizePLAB sensors in PLABStats, to zero after flushing the values to the PLABStats fields. Flush PLABStats values only when retiring the final allocation buffers prior to disposing of a G1ParScanThreadState object, rather than when retiring every allocation buffer.
Reviewed-by: jwilhelm, jmasa, ysr

     1 /*
     2  * Copyright (c) 2001, 2011, 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_SHARED_ALLOCATIONSTATS_HPP
    26 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_ALLOCATIONSTATS_HPP
    28 #ifndef SERIALGC
    29 #include "gc_implementation/shared/gcUtil.hpp"
    30 #include "memory/allocation.hpp"
    31 #include "utilities/globalDefinitions.hpp"
    32 #endif
    34 class AllocationStats VALUE_OBJ_CLASS_SPEC {
    35   // A duration threshold (in ms) used to filter
    36   // possibly unreliable samples.
    37   static float _threshold;
    39   // We measure the demand between the end of the previous sweep and
    40   // beginning of this sweep:
    41   //   Count(end_last_sweep) - Count(start_this_sweep)
    42   //     + split_births(between) - split_deaths(between)
    43   // The above number divided by the time since the end of the
    44   // previous sweep gives us a time rate of demand for blocks
    45   // of this size. We compute a padded average of this rate as
    46   // our current estimate for the time rate of demand for blocks
    47   // of this size. Similarly, we keep a padded average for the time
    48   // between sweeps. Our current estimate for demand for blocks of
    49   // this size is then simply computed as the product of these two
    50   // estimates.
    51   AdaptivePaddedAverage _demand_rate_estimate;
    53   ssize_t     _desired;         // Demand stimate computed as described above
    54   ssize_t     _coal_desired;     // desired +/- small-percent for tuning coalescing
    56   ssize_t     _surplus;         // count - (desired +/- small-percent),
    57                                 // used to tune splitting in best fit
    58   ssize_t     _bfr_surp;         // surplus at start of current sweep
    59   ssize_t     _prev_sweep;       // count from end of previous sweep
    60   ssize_t     _before_sweep;     // count from before current sweep
    61   ssize_t     _coal_births;      // additional chunks from coalescing
    62   ssize_t     _coal_deaths;      // loss from coalescing
    63   ssize_t     _split_births;     // additional chunks from splitting
    64   ssize_t     _split_deaths;     // loss from splitting
    65   size_t      _returned_bytes;   // number of bytes returned to list.
    66  public:
    67   void initialize(bool split_birth = false) {
    68     AdaptivePaddedAverage* dummy =
    69       new (&_demand_rate_estimate) AdaptivePaddedAverage(CMS_FLSWeight,
    70                                                          CMS_FLSPadding);
    71     _desired = 0;
    72     _coal_desired = 0;
    73     _surplus = 0;
    74     _bfr_surp = 0;
    75     _prev_sweep = 0;
    76     _before_sweep = 0;
    77     _coal_births = 0;
    78     _coal_deaths = 0;
    79     _split_births = (split_birth ? 1 : 0);
    80     _split_deaths = 0;
    81     _returned_bytes = 0;
    82   }
    84   AllocationStats() {
    85     initialize();
    86   }
    88   // The rate estimate is in blocks per second.
    89   void compute_desired(size_t count,
    90                        float inter_sweep_current,
    91                        float inter_sweep_estimate,
    92                        float intra_sweep_estimate) {
    93     // If the latest inter-sweep time is below our granularity
    94     // of measurement, we may call in here with
    95     // inter_sweep_current == 0. However, even for suitably small
    96     // but non-zero inter-sweep durations, we may not trust the accuracy
    97     // of accumulated data, since it has not been "integrated"
    98     // (read "low-pass-filtered") long enough, and would be
    99     // vulnerable to noisy glitches. In such cases, we
   100     // ignore the current sample and use currently available
   101     // historical estimates.
   102     assert(prev_sweep() + split_births() + coal_births()        // "Total Production Stock"
   103            >= split_deaths() + coal_deaths() + (ssize_t)count, // "Current stock + depletion"
   104            "Conservation Principle");
   105     if (inter_sweep_current > _threshold) {
   106       ssize_t demand = prev_sweep() - (ssize_t)count + split_births() + coal_births()
   107                        - split_deaths() - coal_deaths();
   108       assert(demand >= 0,
   109              err_msg("Demand (" SSIZE_FORMAT ") should be non-negative for "
   110                      PTR_FORMAT " (size=" SIZE_FORMAT ")",
   111                      demand, this, count));
   112       // Defensive: adjust for imprecision in event counting
   113       if (demand < 0) {
   114         demand = 0;
   115       }
   116       float old_rate = _demand_rate_estimate.padded_average();
   117       float rate = ((float)demand)/inter_sweep_current;
   118       _demand_rate_estimate.sample(rate);
   119       float new_rate = _demand_rate_estimate.padded_average();
   120       ssize_t old_desired = _desired;
   121       float delta_ise = (CMSExtrapolateSweep ? intra_sweep_estimate : 0.0);
   122       _desired = (ssize_t)(new_rate * (inter_sweep_estimate + delta_ise));
   123       if (PrintFLSStatistics > 1) {
   124         gclog_or_tty->print_cr("demand: %d, old_rate: %f, current_rate: %f, new_rate: %f, old_desired: %d, new_desired: %d",
   125                                 demand,     old_rate,     rate,             new_rate,     old_desired,     _desired);
   126       }
   127     }
   128   }
   130   ssize_t desired() const { return _desired; }
   131   void set_desired(ssize_t v) { _desired = v; }
   133   ssize_t coal_desired() const { return _coal_desired; }
   134   void set_coal_desired(ssize_t v) { _coal_desired = v; }
   136   ssize_t surplus() const { return _surplus; }
   137   void set_surplus(ssize_t v) { _surplus = v; }
   138   void increment_surplus() { _surplus++; }
   139   void decrement_surplus() { _surplus--; }
   141   ssize_t bfr_surp() const { return _bfr_surp; }
   142   void set_bfr_surp(ssize_t v) { _bfr_surp = v; }
   143   ssize_t prev_sweep() const { return _prev_sweep; }
   144   void set_prev_sweep(ssize_t v) { _prev_sweep = v; }
   145   ssize_t before_sweep() const { return _before_sweep; }
   146   void set_before_sweep(ssize_t v) { _before_sweep = v; }
   148   ssize_t coal_births() const { return _coal_births; }
   149   void set_coal_births(ssize_t v) { _coal_births = v; }
   150   void increment_coal_births() { _coal_births++; }
   152   ssize_t coal_deaths() const { return _coal_deaths; }
   153   void set_coal_deaths(ssize_t v) { _coal_deaths = v; }
   154   void increment_coal_deaths() { _coal_deaths++; }
   156   ssize_t split_births() const { return _split_births; }
   157   void set_split_births(ssize_t v) { _split_births = v; }
   158   void increment_split_births() { _split_births++; }
   160   ssize_t split_deaths() const { return _split_deaths; }
   161   void set_split_deaths(ssize_t v) { _split_deaths = v; }
   162   void increment_split_deaths() { _split_deaths++; }
   164   NOT_PRODUCT(
   165     size_t returned_bytes() const { return _returned_bytes; }
   166     void set_returned_bytes(size_t v) { _returned_bytes = v; }
   167   )
   168 };
   170 #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_ALLOCATIONSTATS_HPP

mercurial