hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp
author ysr
Wed, 23 Dec 2009 09:23:54 -0800
changeset 4574 b2d5b0975515
parent 1217 5eb97f366a6a
child 5547 f4b087cbb361
permissions -rw-r--r--
6631166: CMS: better heuristics when combatting fragmentation Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking. Reviewed-by: jmasa
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
1217
5eb97f366a6a 6754988: Update copyright year
xdono
parents: 976
diff changeset
     2
 * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    19
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    20
 * CA 95054 USA or visit www.sun.com if you need additional information or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    21
 * have any questions.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
489c9b5090e2 Initial load
duke
parents:
diff changeset
    25
// Catch-all file for utility classes
489c9b5090e2 Initial load
duke
parents:
diff changeset
    26
489c9b5090e2 Initial load
duke
parents:
diff changeset
    27
// A weighted average maintains a running, weighted average
489c9b5090e2 Initial load
duke
parents:
diff changeset
    28
// of some float value (templates would be handy here if we
489c9b5090e2 Initial load
duke
parents:
diff changeset
    29
// need different types).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    30
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    31
// The average is adaptive in that we smooth it for the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    32
// initial samples; we don't use the weight until we have
489c9b5090e2 Initial load
duke
parents:
diff changeset
    33
// enough samples for it to be meaningful.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
// This serves as our best estimate of a future unknown.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
class AdaptiveWeightedAverage : public CHeapObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
  float            _average;        // The last computed average
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
  unsigned         _sample_count;   // How often we've sampled this average
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
  unsigned         _weight;         // The weight used to smooth the averages
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
                                    //   A higher weight favors the most
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
                                    //   recent data.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
 protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
  float            _last_sample;    // The last value sampled.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
  void  increment_count()       { _sample_count++;       }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
  void  set_average(float avg)  { _average = avg;        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
  // Helper function, computes an adaptive weighted average
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
  // given a sample and the last average
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
  float compute_adaptive_average(float new_sample, float average);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
  // Input weight must be between 0 and 100
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
    57
  AdaptiveWeightedAverage(unsigned weight, float avg = 0.0) :
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
    58
    _average(avg), _sample_count(0), _weight(weight), _last_sample(0.0) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
976
241230d48896 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 1
diff changeset
    61
  void clear() {
241230d48896 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 1
diff changeset
    62
    _average = 0;
241230d48896 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 1
diff changeset
    63
    _sample_count = 0;
241230d48896 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 1
diff changeset
    64
    _last_sample = 0;
241230d48896 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 1
diff changeset
    65
  }
241230d48896 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 1
diff changeset
    66
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
    67
  // Useful for modifying static structures after startup.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
    68
  void  modify(size_t avg, unsigned wt, bool force = false)  {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
    69
    assert(force, "Are you sure you want to call this?");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
    70
    _average = (float)avg;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
    71
    _weight  = wt;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
    72
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
    73
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
  // Accessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
  float    average() const       { return _average;       }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
  unsigned weight()  const       { return _weight;        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
  unsigned count()   const       { return _sample_count;  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
  float    last_sample() const   { return _last_sample; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
  // Update data with a new sample.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
  void sample(float new_sample);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
  static inline float exp_avg(float avg, float sample,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
                               unsigned int weight) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
    assert(0 <= weight && weight <= 100, "weight must be a percent");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
    return (100.0F - weight) * avg / 100.0F + weight * sample / 100.0F;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
  static inline size_t exp_avg(size_t avg, size_t sample,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
                               unsigned int weight) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
    // Convert to float and back to avoid integer overflow.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
    return (size_t)exp_avg((float)avg, (float)sample, weight);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
  }
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
    93
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
    94
  // Printing
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
    95
  void print_on(outputStream* st) const;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
    96
  void print() const;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
// A weighted average that includes a deviation from the average,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
// some multiple of which is added to the average.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
// This serves as our best estimate of an upper bound on a future
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
// unknown.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
class AdaptivePaddedAverage : public AdaptiveWeightedAverage {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
  float          _padded_avg;     // The last computed padded average
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
  float          _deviation;      // Running deviation from the average
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
  unsigned       _padding;        // A multiple which, added to the average,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
                                  // gives us an upper bound guess.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
 protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
  void set_padded_average(float avg)  { _padded_avg = avg;  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
  void set_deviation(float dev)       { _deviation  = dev;  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
  AdaptivePaddedAverage() :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
    AdaptiveWeightedAverage(0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
    _padded_avg(0.0), _deviation(0.0), _padding(0) {}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
  AdaptivePaddedAverage(unsigned weight, unsigned padding) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
    AdaptiveWeightedAverage(weight),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
    _padded_avg(0.0), _deviation(0.0), _padding(padding) {}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
  // Placement support
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
  void* operator new(size_t ignored, void* p) { return p; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
  // Allocator
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
  void* operator new(size_t size) { return CHeapObj::operator new(size); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
  // Accessor
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
  float padded_average() const         { return _padded_avg; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
  float deviation()      const         { return _deviation;  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
  unsigned padding()     const         { return _padding;    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
976
241230d48896 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 1
diff changeset
   135
  void clear() {
241230d48896 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 1
diff changeset
   136
    AdaptiveWeightedAverage::clear();
241230d48896 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 1
diff changeset
   137
    _padded_avg = 0;
241230d48896 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 1
diff changeset
   138
    _deviation = 0;
241230d48896 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 1
diff changeset
   139
  }
241230d48896 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 1
diff changeset
   140
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
  // Override
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
  void  sample(float new_sample);
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
   143
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
   144
  // Printing
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
   145
  void print_on(outputStream* st) const;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
   146
  void print() const;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
// A weighted average that includes a deviation from the average,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
// some multiple of which is added to the average.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
// This serves as our best estimate of an upper bound on a future
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
// unknown.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
// A special sort of padded average:  it doesn't update deviations
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
// if the sample is zero. The average is allowed to change. We're
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
// preventing the zero samples from drastically changing our padded
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
// average.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
class AdaptivePaddedNoZeroDevAverage : public AdaptivePaddedAverage {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
  AdaptivePaddedNoZeroDevAverage(unsigned weight, unsigned padding) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
    AdaptivePaddedAverage(weight, padding)  {}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
  // Override
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
  void  sample(float new_sample);
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
   164
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
   165
  // Printing
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
   166
  void print_on(outputStream* st) const;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
   167
  void print() const;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
};
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1217
diff changeset
   169
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
// Use a least squares fit to a set of data to generate a linear
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
// equation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
//              y = intercept + slope * x
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
class LinearLeastSquareFit : public CHeapObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
  double _sum_x;        // sum of all independent data points x
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
  double _sum_x_squared; // sum of all independent data points x**2
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
  double _sum_y;        // sum of all dependent data points y
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
  double _sum_xy;       // sum of all x * y.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
  double _intercept;     // constant term
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
  double _slope;        // slope
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
  // The weighted averages are not currently used but perhaps should
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
  // be used to get decaying averages.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
  AdaptiveWeightedAverage _mean_x; // weighted mean of independent variable
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
  AdaptiveWeightedAverage _mean_y; // weighted mean of dependent variable
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
  LinearLeastSquareFit(unsigned weight);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
  void update(double x, double y);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
  double y(double x);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
  double slope() { return _slope; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
  // Methods to decide if a change in the dependent variable will
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
  // achive a desired goal.  Note that these methods are not
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
  // complementary and both are needed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
  bool decrement_will_decrease();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
  bool increment_will_decrease();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
class GCPauseTimer : StackObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
  elapsedTimer* _timer;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
  GCPauseTimer(elapsedTimer* timer) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
    _timer = timer;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
    _timer->stop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
  ~GCPauseTimer() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
    _timer->start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
};