plab.cpp revision 13242:fcb4803050e8
1/*
2 * Copyright (c) 2001, 2017, 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 */
24
25#include "precompiled.hpp"
26#include "gc/shared/collectedHeap.hpp"
27#include "gc/shared/plab.inline.hpp"
28#include "gc/shared/threadLocalAllocBuffer.hpp"
29#include "logging/log.hpp"
30#include "oops/arrayOop.hpp"
31#include "oops/oop.inline.hpp"
32
33size_t PLAB::min_size() {
34  // Make sure that we return something that is larger than AlignmentReserve
35  return align_object_size(MAX2(MinTLABSize / HeapWordSize, (uintx)oopDesc::header_size())) + AlignmentReserve;
36}
37
38size_t PLAB::max_size() {
39  return ThreadLocalAllocBuffer::max_size();
40}
41
42PLAB::PLAB(size_t desired_plab_sz_) :
43  _word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL),
44  _end(NULL), _hard_end(NULL), _allocated(0), _wasted(0), _undo_wasted(0)
45{
46  // ArrayOopDesc::header_size depends on command line initialization.
47  AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? align_object_size(arrayOopDesc::header_size(T_INT)) : 0;
48  assert(min_size() > AlignmentReserve,
49         "Minimum PLAB size " SIZE_FORMAT " must be larger than alignment reserve " SIZE_FORMAT " "
50         "to be able to contain objects", min_size(), AlignmentReserve);
51}
52
53// If the minimum object size is greater than MinObjAlignment, we can
54// end up with a shard at the end of the buffer that's smaller than
55// the smallest object.  We can't allow that because the buffer must
56// look like it's full of objects when we retire it, so we make
57// sure we have enough space for a filler int array object.
58size_t PLAB::AlignmentReserve;
59
60void PLAB::flush_and_retire_stats(PLABStats* stats) {
61  // Retire the last allocation buffer.
62  size_t unused = retire_internal();
63
64  // Now flush the statistics.
65  stats->add_allocated(_allocated);
66  stats->add_wasted(_wasted);
67  stats->add_undo_wasted(_undo_wasted);
68  stats->add_unused(unused);
69
70  // Since we have flushed the stats we need to clear  the _allocated and _wasted
71  // fields in case somebody retains an instance of this over GCs. Not doing so
72  // will artifically inflate the values in the statistics.
73  _allocated   = 0;
74  _wasted      = 0;
75  _undo_wasted = 0;
76}
77
78void PLAB::retire() {
79  _wasted += retire_internal();
80}
81
82size_t PLAB::retire_internal() {
83  size_t result = 0;
84  if (_top < _hard_end) {
85    CollectedHeap::fill_with_object(_top, _hard_end);
86    result += invalidate();
87  }
88  return result;
89}
90
91void PLAB::add_undo_waste(HeapWord* obj, size_t word_sz) {
92  CollectedHeap::fill_with_object(obj, word_sz);
93  _undo_wasted += word_sz;
94}
95
96void PLAB::undo_last_allocation(HeapWord* obj, size_t word_sz) {
97  assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo");
98  assert(pointer_delta(_top, obj) == word_sz, "Bad undo");
99  _top = obj;
100}
101
102void PLAB::undo_allocation(HeapWord* obj, size_t word_sz) {
103  // Is the alloc in the current alloc buffer?
104  if (contains(obj)) {
105    assert(contains(obj + word_sz - 1),
106      "should contain whole object");
107    undo_last_allocation(obj, word_sz);
108  } else {
109    add_undo_waste(obj, word_sz);
110  }
111}
112
113void PLABStats::log_plab_allocation() {
114  log_debug(gc, plab)("%s PLAB allocation: "
115                      "allocated: " SIZE_FORMAT "B, "
116                      "wasted: " SIZE_FORMAT "B, "
117                      "unused: " SIZE_FORMAT "B, "
118                      "used: " SIZE_FORMAT "B, "
119                      "undo waste: " SIZE_FORMAT "B, ",
120                      _description,
121                      _allocated * HeapWordSize,
122                      _wasted * HeapWordSize,
123                      _unused * HeapWordSize,
124                      used() * HeapWordSize,
125                      _undo_wasted * HeapWordSize);
126}
127
128void PLABStats::log_sizing(size_t calculated_words, size_t net_desired_words) {
129  log_debug(gc, plab)("%s sizing: "
130                      "calculated: " SIZE_FORMAT "B, "
131                      "actual: " SIZE_FORMAT "B",
132                      _description,
133                      calculated_words * HeapWordSize,
134                      net_desired_words * HeapWordSize);
135}
136
137// Calculates plab size for current number of gc worker threads.
138size_t PLABStats::desired_plab_sz(uint no_of_gc_workers) {
139  return align_object_size(MIN2(MAX2(min_size(), _desired_net_plab_sz / no_of_gc_workers), max_size()));
140}
141
142// Compute desired plab size for one gc worker thread and latch result for later
143// use. This should be called once at the end of parallel
144// scavenge; it clears the sensor accumulators.
145void PLABStats::adjust_desired_plab_sz() {
146  log_plab_allocation();
147
148  if (!ResizePLAB) {
149    // Clear accumulators for next round.
150    reset();
151    return;
152  }
153
154  assert(is_object_aligned(max_size()) && min_size() <= max_size(),
155         "PLAB clipping computation may be incorrect");
156
157  assert(_allocated != 0 || _unused == 0,
158         "Inconsistency in PLAB stats: "
159         "_allocated: " SIZE_FORMAT ", "
160         "_wasted: " SIZE_FORMAT ", "
161         "_unused: " SIZE_FORMAT ", "
162         "_undo_wasted: " SIZE_FORMAT,
163         _allocated, _wasted, _unused, _undo_wasted);
164
165  size_t plab_sz = compute_desired_plab_sz();
166  // Take historical weighted average
167  _filter.sample(plab_sz);
168  _desired_net_plab_sz = MAX2(min_size(), (size_t)_filter.average());
169
170  log_sizing(plab_sz, _desired_net_plab_sz);
171  // Clear accumulators for next round
172  reset();
173}
174
175size_t PLABStats::compute_desired_plab_sz() {
176  size_t allocated      = MAX2(_allocated, size_t(1));
177  double wasted_frac    = (double)_unused / (double)allocated;
178  size_t target_refills = (size_t)((wasted_frac * TargetSurvivorRatio) / TargetPLABWastePct);
179  if (target_refills == 0) {
180    target_refills = 1;
181  }
182  size_t used = allocated - _wasted - _unused;
183  // Assumed to have 1 gc worker thread
184  size_t recent_plab_sz = used / target_refills;
185  return recent_plab_sz;
186}
187