view src/share/vm/gc_implementation/shared/allocationStats.hpp @ 10374:87c64c0438fb

6976350: G1: deal with fragmentation while copying objects during GC Summary: Create G1ParGCAllocBufferContainer to contain two buffers instead of previously using one buffer, in order to hold the first priority buffer longer. Thus, when some large objects hits the value of free space left in the first priority buffer it has an alternative to fit in the second priority buffer while the first priority buffer is given more chances to try allocating smaller objects. Overall, it will improve heap space efficiency. Reviewed-by: johnc, jmasa, brutisso Contributed-by: tamao <tao.mao@oracle.com>
author tamao
date Mon, 03 Jun 2013 14:37:13 -0700
parents db9981fd3124
children de88570fabfc
line wrap: on
line source

/*
 * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_ALLOCATIONSTATS_HPP
#define SHARE_VM_GC_IMPLEMENTATION_SHARED_ALLOCATIONSTATS_HPP

#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/shared/gcUtil.hpp"
#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"
#endif // INCLUDE_ALL_GCS

class AllocationStats VALUE_OBJ_CLASS_SPEC {
  // A duration threshold (in ms) used to filter
  // possibly unreliable samples.
  static float _threshold;

  // We measure the demand between the end of the previous sweep and
  // beginning of this sweep:
  //   Count(end_last_sweep) - Count(start_this_sweep)
  //     + split_births(between) - split_deaths(between)
  // The above number divided by the time since the end of the
  // previous sweep gives us a time rate of demand for blocks
  // of this size. We compute a padded average of this rate as
  // our current estimate for the time rate of demand for blocks
  // of this size. Similarly, we keep a padded average for the time
  // between sweeps. Our current estimate for demand for blocks of
  // this size is then simply computed as the product of these two
  // estimates.
  AdaptivePaddedAverage _demand_rate_estimate;

  ssize_t     _desired;         // Demand stimate computed as described above
  ssize_t     _coal_desired;     // desired +/- small-percent for tuning coalescing

  ssize_t     _surplus;         // count - (desired +/- small-percent),
                                // used to tune splitting in best fit
  ssize_t     _bfr_surp;         // surplus at start of current sweep
  ssize_t     _prev_sweep;       // count from end of previous sweep
  ssize_t     _before_sweep;     // count from before current sweep
  ssize_t     _coal_births;      // additional chunks from coalescing
  ssize_t     _coal_deaths;      // loss from coalescing
  ssize_t     _split_births;     // additional chunks from splitting
  ssize_t     _split_deaths;     // loss from splitting
  size_t      _returned_bytes;   // number of bytes returned to list.
 public:
  void initialize(bool split_birth = false) {
    AdaptivePaddedAverage* dummy =
      new (&_demand_rate_estimate) AdaptivePaddedAverage(CMS_FLSWeight,
                                                         CMS_FLSPadding);
    _desired = 0;
    _coal_desired = 0;
    _surplus = 0;
    _bfr_surp = 0;
    _prev_sweep = 0;
    _before_sweep = 0;
    _coal_births = 0;
    _coal_deaths = 0;
    _split_births = (split_birth ? 1 : 0);
    _split_deaths = 0;
    _returned_bytes = 0;
  }

  AllocationStats() {
    initialize();
  }

  // The rate estimate is in blocks per second.
  void compute_desired(size_t count,
                       float inter_sweep_current,
                       float inter_sweep_estimate,
                       float intra_sweep_estimate) {
    // If the latest inter-sweep time is below our granularity
    // of measurement, we may call in here with
    // inter_sweep_current == 0. However, even for suitably small
    // but non-zero inter-sweep durations, we may not trust the accuracy
    // of accumulated data, since it has not been "integrated"
    // (read "low-pass-filtered") long enough, and would be
    // vulnerable to noisy glitches. In such cases, we
    // ignore the current sample and use currently available
    // historical estimates.
    assert(prev_sweep() + split_births() + coal_births()        // "Total Production Stock"
           >= split_deaths() + coal_deaths() + (ssize_t)count, // "Current stock + depletion"
           "Conservation Principle");
    if (inter_sweep_current > _threshold) {
      ssize_t demand = prev_sweep() - (ssize_t)count + split_births() + coal_births()
                       - split_deaths() - coal_deaths();
      assert(demand >= 0,
             err_msg("Demand (" SSIZE_FORMAT ") should be non-negative for "
                     PTR_FORMAT " (size=" SIZE_FORMAT ")",
                     demand, this, count));
      // Defensive: adjust for imprecision in event counting
      if (demand < 0) {
        demand = 0;
      }
      float old_rate = _demand_rate_estimate.padded_average();
      float rate = ((float)demand)/inter_sweep_current;
      _demand_rate_estimate.sample(rate);
      float new_rate = _demand_rate_estimate.padded_average();
      ssize_t old_desired = _desired;
      float delta_ise = (CMSExtrapolateSweep ? intra_sweep_estimate : 0.0);
      _desired = (ssize_t)(new_rate * (inter_sweep_estimate + delta_ise));
      if (PrintFLSStatistics > 1) {
        gclog_or_tty->print_cr("demand: %d, old_rate: %f, current_rate: %f, new_rate: %f, old_desired: %d, new_desired: %d",
                                demand,     old_rate,     rate,             new_rate,     old_desired,     _desired);
      }
    }
  }

  ssize_t desired() const { return _desired; }
  void set_desired(ssize_t v) { _desired = v; }

  ssize_t coal_desired() const { return _coal_desired; }
  void set_coal_desired(ssize_t v) { _coal_desired = v; }

  ssize_t surplus() const { return _surplus; }
  void set_surplus(ssize_t v) { _surplus = v; }
  void increment_surplus() { _surplus++; }
  void decrement_surplus() { _surplus--; }

  ssize_t bfr_surp() const { return _bfr_surp; }
  void set_bfr_surp(ssize_t v) { _bfr_surp = v; }
  ssize_t prev_sweep() const { return _prev_sweep; }
  void set_prev_sweep(ssize_t v) { _prev_sweep = v; }
  ssize_t before_sweep() const { return _before_sweep; }
  void set_before_sweep(ssize_t v) { _before_sweep = v; }

  ssize_t coal_births() const { return _coal_births; }
  void set_coal_births(ssize_t v) { _coal_births = v; }
  void increment_coal_births() { _coal_births++; }

  ssize_t coal_deaths() const { return _coal_deaths; }
  void set_coal_deaths(ssize_t v) { _coal_deaths = v; }
  void increment_coal_deaths() { _coal_deaths++; }

  ssize_t split_births() const { return _split_births; }
  void set_split_births(ssize_t v) { _split_births = v; }
  void increment_split_births() { _split_births++; }

  ssize_t split_deaths() const { return _split_deaths; }
  void set_split_deaths(ssize_t v) { _split_deaths = v; }
  void increment_split_deaths() { _split_deaths++; }

  NOT_PRODUCT(
    size_t returned_bytes() const { return _returned_bytes; }
    void set_returned_bytes(size_t v) { _returned_bytes = v; }
  )
};

#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_ALLOCATIONSTATS_HPP