Fri, 10 Oct 2014 15:51:58 +0200
8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso
1 /*
2 * Copyright (c) 2001, 2013, 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_COLLECTIONSETCHOOSER_HPP
26 #define SHARE_VM_GC_IMPLEMENTATION_G1_COLLECTIONSETCHOOSER_HPP
28 #include "gc_implementation/g1/heapRegion.hpp"
29 #include "utilities/growableArray.hpp"
31 class CollectionSetChooser: public CHeapObj<mtGC> {
33 GrowableArray<HeapRegion*> _regions;
35 // Unfortunately, GrowableArray uses ints for length and indexes. To
36 // avoid excessive casting in the rest of the class the following
37 // wrapper methods are provided that use uints.
39 uint regions_length() { return (uint) _regions.length(); }
40 HeapRegion* regions_at(uint i) { return _regions.at((int) i); }
41 void regions_at_put(uint i, HeapRegion* hr) {
42 _regions.at_put((int) i, hr);
43 }
44 void regions_at_put_grow(uint i, HeapRegion* hr) {
45 _regions.at_put_grow((int) i, hr);
46 }
47 void regions_trunc_to(uint i) { _regions.trunc_to((uint) i); }
49 // The index of the next candidate old region to be considered for
50 // addition to the CSet.
51 uint _curr_index;
53 // The number of candidate old regions added to the CSet chooser.
54 // Note: this is not updated when removing a region using
55 // remove_and_move_to_next() below.
56 uint _length;
58 // Keeps track of the start of the next array chunk to be claimed by
59 // parallel GC workers.
60 uint _first_par_unreserved_idx;
62 // If a region has more live bytes than this threshold, it will not
63 // be added to the CSet chooser and will not be a candidate for
64 // collection.
65 size_t _region_live_threshold_bytes;
67 // The sum of reclaimable bytes over all the regions in the CSet chooser.
68 size_t _remaining_reclaimable_bytes;
70 public:
72 // Return the current candidate region to be considered for
73 // collection without removing it from the CSet chooser.
74 HeapRegion* peek() {
75 HeapRegion* res = NULL;
76 if (_curr_index < _length) {
77 res = regions_at(_curr_index);
78 assert(res != NULL,
79 err_msg("Unexpected NULL hr in _regions at index %u",
80 _curr_index));
81 }
82 return res;
83 }
85 // Remove the given region from the CSet chooser and move to the
86 // next one. The given region should be the current candidate region
87 // in the CSet chooser.
88 void remove_and_move_to_next(HeapRegion* hr) {
89 assert(hr != NULL, "pre-condition");
90 assert(_curr_index < _length, "pre-condition");
91 assert(regions_at(_curr_index) == hr, "pre-condition");
92 regions_at_put(_curr_index, NULL);
93 assert(hr->reclaimable_bytes() <= _remaining_reclaimable_bytes,
94 err_msg("remaining reclaimable bytes inconsistent "
95 "from region: "SIZE_FORMAT" remaining: "SIZE_FORMAT,
96 hr->reclaimable_bytes(), _remaining_reclaimable_bytes));
97 _remaining_reclaimable_bytes -= hr->reclaimable_bytes();
98 _curr_index += 1;
99 }
101 CollectionSetChooser();
103 void sort_regions();
105 // Determine whether to add the given region to the CSet chooser or
106 // not. Currently, we skip humongous regions (we never add them to
107 // the CSet, we only reclaim them during cleanup) and regions whose
108 // live bytes are over the threshold.
109 bool should_add(HeapRegion* hr) {
110 assert(hr->is_marked(), "pre-condition");
111 assert(!hr->is_young(), "should never consider young regions");
112 return !hr->isHumongous() &&
113 hr->live_bytes() < _region_live_threshold_bytes;
114 }
116 // Returns the number candidate old regions added
117 uint length() { return _length; }
119 // Serial version.
120 void add_region(HeapRegion *hr);
122 // Must be called before calls to claim_array_chunk().
123 // n_regions is the number of regions, chunk_size the chunk size.
124 void prepare_for_par_region_addition(uint n_regions, uint chunk_size);
125 // Returns the first index in a contiguous chunk of chunk_size indexes
126 // that the calling thread has reserved. These must be set by the
127 // calling thread using set_region() (to NULL if necessary).
128 uint claim_array_chunk(uint chunk_size);
129 // Set the marked array entry at index to hr. Careful to claim the index
130 // first if in parallel.
131 void set_region(uint index, HeapRegion* hr);
132 // Atomically increment the number of added regions by region_num
133 // and the amount of reclaimable bytes by reclaimable_bytes.
134 void update_totals(uint region_num, size_t reclaimable_bytes);
136 void clear();
138 // Return the number of candidate regions that remain to be collected.
139 uint remaining_regions() { return _length - _curr_index; }
141 // Determine whether the CSet chooser has more candidate regions or not.
142 bool is_empty() { return remaining_regions() == 0; }
144 // Return the reclaimable bytes that remain to be collected on
145 // all the candidate regions in the CSet chooser.
146 size_t remaining_reclaimable_bytes() { return _remaining_reclaimable_bytes; }
148 // Returns true if the used portion of "_regions" is properly
149 // sorted, otherwise asserts false.
150 void verify() PRODUCT_RETURN;
151 };
153 class CSetChooserParUpdater : public StackObj {
154 private:
155 CollectionSetChooser* _chooser;
156 bool _parallel;
157 uint _chunk_size;
158 uint _cur_chunk_idx;
159 uint _cur_chunk_end;
160 uint _regions_added;
161 size_t _reclaimable_bytes_added;
163 public:
164 CSetChooserParUpdater(CollectionSetChooser* chooser,
165 bool parallel, uint chunk_size) :
166 _chooser(chooser), _parallel(parallel), _chunk_size(chunk_size),
167 _cur_chunk_idx(0), _cur_chunk_end(0),
168 _regions_added(0), _reclaimable_bytes_added(0) { }
170 ~CSetChooserParUpdater() {
171 if (_parallel && _regions_added > 0) {
172 _chooser->update_totals(_regions_added, _reclaimable_bytes_added);
173 }
174 }
176 void add_region(HeapRegion* hr) {
177 if (_parallel) {
178 if (_cur_chunk_idx == _cur_chunk_end) {
179 _cur_chunk_idx = _chooser->claim_array_chunk(_chunk_size);
180 _cur_chunk_end = _cur_chunk_idx + _chunk_size;
181 }
182 assert(_cur_chunk_idx < _cur_chunk_end, "invariant");
183 _chooser->set_region(_cur_chunk_idx, hr);
184 _cur_chunk_idx += 1;
185 } else {
186 _chooser->add_region(hr);
187 }
188 _regions_added += 1;
189 _reclaimable_bytes_added += hr->reclaimable_bytes();
190 }
192 bool should_add(HeapRegion* hr) { return _chooser->should_add(hr); }
193 };
195 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_COLLECTIONSETCHOOSER_HPP