Tue, 21 Aug 2012 14:10:39 -0700
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_G1ALLOCREGION_HPP
26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1ALLOCREGION_HPP
28 #include "gc_implementation/g1/heapRegion.hpp"
30 class G1CollectedHeap;
32 // 0 -> no tracing, 1 -> basic tracing, 2 -> basic + allocation tracing
33 #define G1_ALLOC_REGION_TRACING 0
35 class ar_ext_msg;
37 // A class that holds a region that is active in satisfying allocation
38 // requests, potentially issued in parallel. When the active region is
39 // full it will be retired and replaced with a new one. The
40 // implementation assumes that fast-path allocations will be lock-free
41 // and a lock will need to be taken when the active region needs to be
42 // replaced.
44 class G1AllocRegion VALUE_OBJ_CLASS_SPEC {
45 friend class ar_ext_msg;
47 private:
48 // The active allocating region we are currently allocating out
49 // of. The invariant is that if this object is initialized (i.e.,
50 // init() has been called and release() has not) then _alloc_region
51 // is either an active allocating region or the dummy region (i.e.,
52 // it can never be NULL) and this object can be used to satisfy
53 // allocation requests. If this object is not initialized
54 // (i.e. init() has not been called or release() has been called)
55 // then _alloc_region is NULL and this object should not be used to
56 // satisfy allocation requests (it was done this way to force the
57 // correct use of init() and release()).
58 HeapRegion* _alloc_region;
60 // It keeps track of the distinct number of regions that are used
61 // for allocation in the active interval of this object, i.e.,
62 // between a call to init() and a call to release(). The count
63 // mostly includes regions that are freshly allocated, as well as
64 // the region that is re-used using the set() method. This count can
65 // be used in any heuristics that might want to bound how many
66 // distinct regions this object can used during an active interval.
67 uint _count;
69 // When we set up a new active region we save its used bytes in this
70 // field so that, when we retire it, we can calculate how much space
71 // we allocated in it.
72 size_t _used_bytes_before;
74 // When true, indicates that allocate calls should do BOT updates.
75 const bool _bot_updates;
77 // Useful for debugging and tracing.
78 const char* _name;
80 // A dummy region (i.e., it's been allocated specially for this
81 // purpose and it is not part of the heap) that is full (i.e., top()
82 // == end()). When we don't have a valid active region we make
83 // _alloc_region point to this. This allows us to skip checking
84 // whether the _alloc_region is NULL or not.
85 static HeapRegion* _dummy_region;
87 // Some of the methods below take a bot_updates parameter. Its value
88 // should be the same as the _bot_updates field. The idea is that
89 // the parameter will be a constant for a particular alloc region
90 // and, given that these methods will be hopefully inlined, the
91 // compiler should compile out the test.
93 // Perform a non-MT-safe allocation out of the given region.
94 static inline HeapWord* allocate(HeapRegion* alloc_region,
95 size_t word_size,
96 bool bot_updates);
98 // Perform a MT-safe allocation out of the given region.
99 static inline HeapWord* par_allocate(HeapRegion* alloc_region,
100 size_t word_size,
101 bool bot_updates);
103 // Ensure that the region passed as a parameter has been filled up
104 // so that noone else can allocate out of it any more.
105 static void fill_up_remaining_space(HeapRegion* alloc_region,
106 bool bot_updates);
108 // Retire the active allocating region. If fill_up is true then make
109 // sure that the region is full before we retire it so that noone
110 // else can allocate out of it.
111 void retire(bool fill_up);
113 // Allocate a new active region and use it to perform a word_size
114 // allocation. The force parameter will be passed on to
115 // G1CollectedHeap::allocate_new_alloc_region() and tells it to try
116 // to allocate a new region even if the max has been reached.
117 HeapWord* new_alloc_region_and_allocate(size_t word_size, bool force);
119 void fill_in_ext_msg(ar_ext_msg* msg, const char* message);
121 protected:
122 // For convenience as subclasses use it.
123 static G1CollectedHeap* _g1h;
125 virtual HeapRegion* allocate_new_region(size_t word_size, bool force) = 0;
126 virtual void retire_region(HeapRegion* alloc_region,
127 size_t allocated_bytes) = 0;
129 G1AllocRegion(const char* name, bool bot_updates);
131 public:
132 static void setup(G1CollectedHeap* g1h, HeapRegion* dummy_region);
134 HeapRegion* get() const {
135 // Make sure that the dummy region does not escape this class.
136 return (_alloc_region == _dummy_region) ? NULL : _alloc_region;
137 }
139 uint count() { return _count; }
141 // The following two are the building blocks for the allocation method.
143 // First-level allocation: Should be called without holding a
144 // lock. It will try to allocate lock-free out of the active region,
145 // or return NULL if it was unable to.
146 inline HeapWord* attempt_allocation(size_t word_size, bool bot_updates);
148 // Second-level allocation: Should be called while holding a
149 // lock. It will try to first allocate lock-free out of the active
150 // region or, if it's unable to, it will try to replace the active
151 // alloc region with a new one. We require that the caller takes the
152 // appropriate lock before calling this so that it is easier to make
153 // it conform to its locking protocol.
154 inline HeapWord* attempt_allocation_locked(size_t word_size,
155 bool bot_updates);
157 // Should be called to allocate a new region even if the max of this
158 // type of regions has been reached. Should only be called if other
159 // allocation attempts have failed and we are not holding a valid
160 // active region.
161 inline HeapWord* attempt_allocation_force(size_t word_size,
162 bool bot_updates);
164 // Should be called before we start using this object.
165 void init();
167 // This can be used to set the active region to a specific
168 // region. (Use Example: we try to retain the last old GC alloc
169 // region that we've used during a GC and we can use set() to
170 // re-instate it at the beginning of the next GC.)
171 void set(HeapRegion* alloc_region);
173 // Should be called when we want to release the active region which
174 // is returned after it's been retired.
175 HeapRegion* release();
177 #if G1_ALLOC_REGION_TRACING
178 void trace(const char* str, size_t word_size = 0, HeapWord* result = NULL);
179 #else // G1_ALLOC_REGION_TRACING
180 void trace(const char* str, size_t word_size = 0, HeapWord* result = NULL) { }
181 #endif // G1_ALLOC_REGION_TRACING
182 };
184 class ar_ext_msg : public err_msg {
185 public:
186 ar_ext_msg(G1AllocRegion* alloc_region, const char *message) : err_msg("") {
187 alloc_region->fill_in_ext_msg(this, message);
188 }
189 };
191 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1ALLOCREGION_HPP