Mercurial > hg > graal-jvmci-8
comparison src/share/vm/gc_implementation/g1/collectionSetChooser.hpp @ 4912:a9647476d1a4
7132029: G1: mixed GC phase lasts for longer than it should
Summary: Revamp of the mechanism that chooses old regions for inclusion in the CSet. It simplifies the code and introduces min and max bounds on the number of old regions added to the CSet at each mixed GC to avoid pathological cases. It also ensures that when we do a mixed GC we'll always find old regions to add to the CSet (i.e., it eliminates the case where a mixed GC will collect no old regions which can happen today).
Reviewed-by: johnc, brutisso
author | tonyp |
---|---|
date | Wed, 15 Feb 2012 13:06:53 -0500 |
parents | b9390528617c |
children | 720b6a76dd9d |
comparison
equal
deleted
inserted
replaced
4911:d903bf750e9f | 4912:a9647476d1a4 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_COLLECTIONSETCHOOSER_HPP | 25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_COLLECTIONSETCHOOSER_HPP |
26 #define SHARE_VM_GC_IMPLEMENTATION_G1_COLLECTIONSETCHOOSER_HPP | 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_COLLECTIONSETCHOOSER_HPP |
27 | 27 |
28 #include "gc_implementation/g1/heapRegion.hpp" | 28 #include "gc_implementation/g1/heapRegion.hpp" |
29 #include "utilities/growableArray.hpp" | 29 #include "utilities/growableArray.hpp" |
30 | |
31 // We need to sort heap regions by collection desirability. | |
32 // This sorting is currently done in two "stages". An initial sort is | |
33 // done following a cleanup pause as soon as all of the marked but | |
34 // non-empty regions have been identified and the completely empty | |
35 // ones reclaimed. | |
36 // This gives us a global sort on a GC efficiency metric | |
37 // based on predictive data available at that time. However, | |
38 // any of these regions that are collected will only be collected | |
39 // during a future GC pause, by which time it is possible that newer | |
40 // data might allow us to revise and/or refine the earlier | |
41 // pause predictions, leading to changes in expected gc efficiency | |
42 // order. To somewhat mitigate this obsolescence, more so in the | |
43 // case of regions towards the end of the list, which will be | |
44 // picked later, these pre-sorted regions from the _markedRegions | |
45 // array are not used as is, but a small prefix thereof is | |
46 // insertion-sorted again into a small cache, based on more | |
47 // recent remembered set information. Regions are then drawn | |
48 // from this cache to construct the collection set at each | |
49 // incremental GC. | |
50 // This scheme and/or its implementation may be subject to | |
51 // revision in the future. | |
52 | 30 |
53 class CSetChooserCache VALUE_OBJ_CLASS_SPEC { | 31 class CSetChooserCache VALUE_OBJ_CLASS_SPEC { |
54 private: | 32 private: |
55 enum { | 33 enum { |
56 CacheLength = 16 | 34 CacheLength = 16 |
101 }; | 79 }; |
102 | 80 |
103 class CollectionSetChooser: public CHeapObj { | 81 class CollectionSetChooser: public CHeapObj { |
104 | 82 |
105 GrowableArray<HeapRegion*> _markedRegions; | 83 GrowableArray<HeapRegion*> _markedRegions; |
106 int _curMarkedIndex; | 84 |
107 int _numMarkedRegions; | 85 // The index of the next candidate old region to be considered for |
86 // addition to the CSet. | |
87 int _curr_index; | |
88 | |
89 // The number of candidate old regions added to the CSet chooser. | |
90 int _length; | |
91 | |
108 CSetChooserCache _cache; | 92 CSetChooserCache _cache; |
109 | |
110 // True iff last collection pause ran of out new "age 0" regions, and | |
111 // returned an "age 1" region. | |
112 bool _unmarked_age_1_returned_as_new; | |
113 | |
114 jint _first_par_unreserved_idx; | 93 jint _first_par_unreserved_idx; |
115 | 94 |
95 // If a region has more live bytes than this threshold, it will not | |
96 // be added to the CSet chooser and will not be a candidate for | |
97 // collection. | |
98 size_t _regionLiveThresholdBytes; | |
99 | |
100 // The sum of reclaimable bytes over all the regions in the CSet chooser. | |
101 size_t _remainingReclaimableBytes; | |
102 | |
116 public: | 103 public: |
117 | 104 |
118 HeapRegion* getNextMarkedRegion(double time_so_far, double avg_prediction); | 105 // Return the current candidate region to be considered for |
106 // collection without removing it from the CSet chooser. | |
107 HeapRegion* peek() { | |
108 HeapRegion* res = NULL; | |
109 if (_curr_index < _length) { | |
110 res = _markedRegions.at(_curr_index); | |
111 assert(res != NULL, | |
112 err_msg("Unexpected NULL hr in _markedRegions at index %d", | |
113 _curr_index)); | |
114 } | |
115 return res; | |
116 } | |
117 | |
118 // Remove the given region from the CSet chooser and move to the | |
119 // next one. The given region should be the current candidate region | |
120 // in the CSet chooser. | |
121 void remove_and_move_to_next(HeapRegion* hr) { | |
122 assert(hr != NULL, "pre-condition"); | |
123 assert(_curr_index < _length, "pre-condition"); | |
124 assert(_markedRegions.at(_curr_index) == hr, "pre-condition"); | |
125 hr->set_sort_index(-1); | |
126 _markedRegions.at_put(_curr_index, NULL); | |
127 assert(hr->reclaimable_bytes() <= _remainingReclaimableBytes, | |
128 err_msg("remaining reclaimable bytes inconsistent " | |
129 "from region: "SIZE_FORMAT" remaining: "SIZE_FORMAT, | |
130 hr->reclaimable_bytes(), _remainingReclaimableBytes)); | |
131 _remainingReclaimableBytes -= hr->reclaimable_bytes(); | |
132 _curr_index += 1; | |
133 } | |
119 | 134 |
120 CollectionSetChooser(); | 135 CollectionSetChooser(); |
121 | 136 |
122 void sortMarkedHeapRegions(); | 137 void sortMarkedHeapRegions(); |
123 void fillCache(); | 138 void fillCache(); |
139 | |
140 // Determine whether to add the given region to the CSet chooser or | |
141 // not. Currently, we skip humongous regions (we never add them to | |
142 // the CSet, we only reclaim them during cleanup) and regions whose | |
143 // live bytes are over the threshold. | |
144 bool shouldAdd(HeapRegion* hr) { | |
145 assert(hr->is_marked(), "pre-condition"); | |
146 assert(!hr->is_young(), "should never consider young regions"); | |
147 return !hr->isHumongous() && | |
148 hr->live_bytes() < _regionLiveThresholdBytes; | |
149 } | |
150 | |
151 // Calculate the minimum number of old regions we'll add to the CSet | |
152 // during a mixed GC. | |
153 size_t calcMinOldCSetLength(); | |
154 | |
155 // Calculate the maximum number of old regions we'll add to the CSet | |
156 // during a mixed GC. | |
157 size_t calcMaxOldCSetLength(); | |
158 | |
159 // Serial version. | |
124 void addMarkedHeapRegion(HeapRegion *hr); | 160 void addMarkedHeapRegion(HeapRegion *hr); |
125 | 161 |
126 // Must be called before calls to getParMarkedHeapRegionChunk. | 162 // Must be called before calls to getParMarkedHeapRegionChunk. |
127 // "n_regions" is the number of regions, "chunkSize" the chunk size. | 163 // "n_regions" is the number of regions, "chunkSize" the chunk size. |
128 void prepareForAddMarkedHeapRegionsPar(size_t n_regions, size_t chunkSize); | 164 void prepareForAddMarkedHeapRegionsPar(size_t n_regions, size_t chunkSize); |
131 // calling thread using "setMarkedHeapRegion" (to NULL if necessary). | 167 // calling thread using "setMarkedHeapRegion" (to NULL if necessary). |
132 jint getParMarkedHeapRegionChunk(jint n_regions); | 168 jint getParMarkedHeapRegionChunk(jint n_regions); |
133 // Set the marked array entry at index to hr. Careful to claim the index | 169 // Set the marked array entry at index to hr. Careful to claim the index |
134 // first if in parallel. | 170 // first if in parallel. |
135 void setMarkedHeapRegion(jint index, HeapRegion* hr); | 171 void setMarkedHeapRegion(jint index, HeapRegion* hr); |
136 // Atomically increment the number of claimed regions by "inc_by". | 172 // Atomically increment the number of added regions by region_num |
137 void incNumMarkedHeapRegions(jint inc_by); | 173 // and the amount of reclaimable bytes by reclaimable_bytes. |
174 void updateTotals(jint region_num, size_t reclaimable_bytes); | |
138 | 175 |
139 void clearMarkedHeapRegions(); | 176 void clearMarkedHeapRegions(); |
140 | 177 |
141 void updateAfterFullCollection(); | 178 // Return the number of candidate regions that remain to be collected. |
142 | 179 size_t remainingRegions() { return _length - _curr_index; } |
143 bool unmarked_age_1_returned_as_new() { return _unmarked_age_1_returned_as_new; } | 180 |
181 // Determine whether the CSet chooser has more candidate regions or not. | |
182 bool isEmpty() { return remainingRegions() == 0; } | |
183 | |
184 // Return the reclaimable bytes that remain to be collected on | |
185 // all the candidate regions in the CSet chooser. | |
186 size_t remainingReclaimableBytes () { return _remainingReclaimableBytes; } | |
144 | 187 |
145 // Returns true if the used portion of "_markedRegions" is properly | 188 // Returns true if the used portion of "_markedRegions" is properly |
146 // sorted, otherwise asserts false. | 189 // sorted, otherwise asserts false. |
147 #ifndef PRODUCT | 190 #ifndef PRODUCT |
148 bool verify(void); | 191 bool verify(void); |
149 bool regionProperlyOrdered(HeapRegion* r) { | 192 bool regionProperlyOrdered(HeapRegion* r) { |
150 int si = r->sort_index(); | 193 int si = r->sort_index(); |
151 return (si == -1) || | 194 if (si > -1) { |
152 (si > -1 && _markedRegions.at(si) == r) || | 195 guarantee(_curr_index <= si && si < _length, |
153 (si < -1 && _cache.region_in_cache(r)); | 196 err_msg("curr: %d sort index: %d: length: %d", |
197 _curr_index, si, _length)); | |
198 guarantee(_markedRegions.at(si) == r, | |
199 err_msg("sort index: %d at: "PTR_FORMAT" r: "PTR_FORMAT, | |
200 si, _markedRegions.at(si), r)); | |
201 } else { | |
202 guarantee(si == -1, err_msg("sort index: %d", si)); | |
203 } | |
204 return true; | |
154 } | 205 } |
155 #endif | 206 #endif |
156 | 207 |
157 }; | 208 }; |
158 | 209 |