Mercurial > hg > graal-compiler
annotate src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp @ 2149:7e37af9d69ef
7011379: G1: overly long concurrent marking cycles
Summary: This changeset introduces filtering of SATB buffers at the point when they are about to be enqueued. If this filtering clears enough entries on each buffer, the buffer can then be re-used and not enqueued. This cuts down the number of SATB buffers that need to be processed by the concurrent marking threads.
Reviewed-by: johnc, ysr
author | tonyp |
---|---|
date | Wed, 19 Jan 2011 09:35:17 -0500 |
parents | f95d63e2154a |
children | da91efe96a93 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1387
diff
changeset
|
2 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1387
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1387
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1387
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSADAPTIVESIZEPOLICY_HPP |
26 #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSADAPTIVESIZEPOLICY_HPP | |
27 | |
28 #include "gc_implementation/shared/adaptiveSizePolicy.hpp" | |
29 #include "gc_implementation/shared/gcStats.hpp" | |
30 #include "gc_implementation/shared/gcUtil.hpp" | |
31 #include "gc_interface/gcCause.hpp" | |
32 | |
0 | 33 // This class keeps statistical information and computes the |
34 // optimal free space for both the young and old generation | |
35 // based on current application characteristics (based on gc cost | |
36 // and application footprint). | |
37 // | |
38 // It also computes an optimal tenuring threshold between the young | |
39 // and old generations, so as to equalize the cost of collections | |
40 // of those generations, as well as optimial survivor space sizes | |
41 // for the young generation. | |
42 // | |
43 // While this class is specifically intended for a generational system | |
44 // consisting of a young gen (containing an Eden and two semi-spaces) | |
45 // and a tenured gen, as well as a perm gen for reflective data, it | |
46 // makes NO references to specific generations. | |
47 // | |
48 // 05/02/2003 Update | |
49 // The 1.5 policy makes use of data gathered for the costs of GC on | |
50 // specific generations. That data does reference specific | |
51 // generation. Also diagnostics specific to generations have | |
52 // been added. | |
53 | |
54 // Forward decls | |
55 class elapsedTimer; | |
1387
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
56 class GenerationSizer; |
0 | 57 |
58 class PSAdaptiveSizePolicy : public AdaptiveSizePolicy { | |
59 friend class PSGCAdaptivePolicyCounters; | |
60 private: | |
61 // These values are used to record decisions made during the | |
62 // policy. For example, if the young generation was decreased | |
63 // to decrease the GC cost of minor collections the value | |
64 // decrease_young_gen_for_throughput_true is used. | |
65 | |
66 // Last calculated sizes, in bytes, and aligned | |
67 // NEEDS_CLEANUP should use sizes.hpp, but it works in ints, not size_t's | |
68 | |
69 // Time statistics | |
70 AdaptivePaddedAverage* _avg_major_pause; | |
71 | |
72 // Footprint statistics | |
73 AdaptiveWeightedAverage* _avg_base_footprint; | |
74 | |
75 // Statistical data gathered for GC | |
76 GCStats _gc_stats; | |
77 | |
78 size_t _survivor_size_limit; // Limit in bytes of survivor size | |
79 const double _collection_cost_margin_fraction; | |
80 | |
81 // Variable for estimating the major and minor pause times. | |
82 // These variables represent linear least-squares fits of | |
83 // the data. | |
84 // major pause time vs. old gen size | |
85 LinearLeastSquareFit* _major_pause_old_estimator; | |
86 // major pause time vs. young gen size | |
87 LinearLeastSquareFit* _major_pause_young_estimator; | |
88 | |
89 | |
90 // These record the most recent collection times. They | |
91 // are available as an alternative to using the averages | |
92 // for making ergonomic decisions. | |
93 double _latest_major_mutator_interval_seconds; | |
94 | |
95 const size_t _intra_generation_alignment; // alignment for eden, survivors | |
96 | |
97 const double _gc_minor_pause_goal_sec; // goal for maximum minor gc pause | |
98 | |
99 // The amount of live data in the heap at the last full GC, used | |
100 // as a baseline to help us determine when we need to perform the | |
101 // next full GC. | |
102 size_t _live_at_last_full_gc; | |
103 | |
104 // decrease/increase the old generation for minor pause time | |
105 int _change_old_gen_for_min_pauses; | |
106 | |
107 // increase/decrease the young generation for major pause time | |
108 int _change_young_gen_for_maj_pauses; | |
109 | |
110 | |
111 // Flag indicating that the adaptive policy is ready to use | |
112 bool _old_gen_policy_is_ready; | |
113 | |
114 // Changing the generation sizing depends on the data that is | |
115 // gathered about the effects of changes on the pause times and | |
116 // throughput. These variable count the number of data points | |
117 // gathered. The policy may use these counters as a threshhold | |
118 // for reliable data. | |
119 julong _young_gen_change_for_major_pause_count; | |
120 | |
121 // To facilitate faster growth at start up, supplement the normal | |
122 // growth percentage for the young gen eden and the | |
123 // old gen space for promotion with these value which decay | |
124 // with increasing collections. | |
125 uint _young_gen_size_increment_supplement; | |
126 uint _old_gen_size_increment_supplement; | |
127 | |
128 // The number of bytes absorbed from eden into the old gen by moving the | |
129 // boundary over live data. | |
130 size_t _bytes_absorbed_from_eden; | |
131 | |
132 private: | |
133 | |
134 // Accessors | |
135 AdaptivePaddedAverage* avg_major_pause() const { return _avg_major_pause; } | |
136 double gc_minor_pause_goal_sec() const { return _gc_minor_pause_goal_sec; } | |
137 | |
138 // Change the young generation size to achieve a minor GC pause time goal | |
139 void adjust_for_minor_pause_time(bool is_full_gc, | |
140 size_t* desired_promo_size_ptr, | |
141 size_t* desired_eden_size_ptr); | |
142 // Change the generation sizes to achieve a GC pause time goal | |
143 // Returned sizes are not necessarily aligned. | |
144 void adjust_for_pause_time(bool is_full_gc, | |
145 size_t* desired_promo_size_ptr, | |
146 size_t* desired_eden_size_ptr); | |
147 // Change the generation sizes to achieve an application throughput goal | |
148 // Returned sizes are not necessarily aligned. | |
149 void adjust_for_throughput(bool is_full_gc, | |
150 size_t* desired_promo_size_ptr, | |
151 size_t* desired_eden_size_ptr); | |
152 // Change the generation sizes to achieve minimum footprint | |
153 // Returned sizes are not aligned. | |
154 size_t adjust_promo_for_footprint(size_t desired_promo_size, | |
155 size_t desired_total); | |
156 size_t adjust_eden_for_footprint(size_t desired_promo_size, | |
157 size_t desired_total); | |
158 | |
159 // Size in bytes for an increment or decrement of eden. | |
160 virtual size_t eden_increment(size_t cur_eden, uint percent_change); | |
161 virtual size_t eden_decrement(size_t cur_eden); | |
162 size_t eden_decrement_aligned_down(size_t cur_eden); | |
163 size_t eden_increment_with_supplement_aligned_up(size_t cur_eden); | |
164 | |
165 // Size in bytes for an increment or decrement of the promotion area | |
166 virtual size_t promo_increment(size_t cur_promo, uint percent_change); | |
167 virtual size_t promo_decrement(size_t cur_promo); | |
168 size_t promo_decrement_aligned_down(size_t cur_promo); | |
169 size_t promo_increment_with_supplement_aligned_up(size_t cur_promo); | |
170 | |
171 // Decay the supplemental growth additive. | |
172 void decay_supplemental_growth(bool is_full_gc); | |
173 | |
174 // Returns a change that has been scaled down. Result | |
175 // is not aligned. (If useful, move to some shared | |
176 // location.) | |
177 size_t scale_down(size_t change, double part, double total); | |
178 | |
179 protected: | |
180 // Time accessors | |
181 | |
182 // Footprint accessors | |
183 size_t live_space() const { | |
184 return (size_t)(avg_base_footprint()->average() + | |
185 avg_young_live()->average() + | |
186 avg_old_live()->average()); | |
187 } | |
188 size_t free_space() const { | |
189 return _eden_size + _promo_size; | |
190 } | |
191 | |
192 void set_promo_size(size_t new_size) { | |
193 _promo_size = new_size; | |
194 } | |
195 void set_survivor_size(size_t new_size) { | |
196 _survivor_size = new_size; | |
197 } | |
198 | |
199 // Update estimators | |
200 void update_minor_pause_old_estimator(double minor_pause_in_ms); | |
201 | |
202 virtual GCPolicyKind kind() const { return _gc_ps_adaptive_size_policy; } | |
203 | |
204 public: | |
205 // Use by ASPSYoungGen and ASPSOldGen to limit boundary moving. | |
206 size_t eden_increment_aligned_up(size_t cur_eden); | |
207 size_t eden_increment_aligned_down(size_t cur_eden); | |
208 size_t promo_increment_aligned_up(size_t cur_promo); | |
209 size_t promo_increment_aligned_down(size_t cur_promo); | |
210 | |
211 virtual size_t eden_increment(size_t cur_eden); | |
212 virtual size_t promo_increment(size_t cur_promo); | |
213 | |
214 // Accessors for use by performance counters | |
215 AdaptivePaddedNoZeroDevAverage* avg_promoted() const { | |
216 return _gc_stats.avg_promoted(); | |
217 } | |
218 AdaptiveWeightedAverage* avg_base_footprint() const { | |
219 return _avg_base_footprint; | |
220 } | |
221 | |
222 // Input arguments are initial free space sizes for young and old | |
223 // generations, the initial survivor space size, the | |
224 // alignment values and the pause & throughput goals. | |
225 // | |
226 // NEEDS_CLEANUP this is a singleton object | |
227 PSAdaptiveSizePolicy(size_t init_eden_size, | |
228 size_t init_promo_size, | |
229 size_t init_survivor_size, | |
230 size_t intra_generation_alignment, | |
231 double gc_pause_goal_sec, | |
232 double gc_minor_pause_goal_sec, | |
233 uint gc_time_ratio); | |
234 | |
235 // Methods indicating events of interest to the adaptive size policy, | |
236 // called by GC algorithms. It is the responsibility of users of this | |
237 // policy to call these methods at the correct times! | |
238 void major_collection_begin(); | |
239 void major_collection_end(size_t amount_live, GCCause::Cause gc_cause); | |
240 | |
241 // | |
242 void tenured_allocation(size_t size) { | |
243 _avg_pretenured->sample(size); | |
244 } | |
245 | |
246 // Accessors | |
247 // NEEDS_CLEANUP should use sizes.hpp | |
248 | |
249 size_t calculated_old_free_size_in_bytes() const { | |
250 return (size_t)(_promo_size + avg_promoted()->padded_average()); | |
251 } | |
252 | |
253 size_t average_old_live_in_bytes() const { | |
254 return (size_t) avg_old_live()->average(); | |
255 } | |
256 | |
257 size_t average_promoted_in_bytes() const { | |
258 return (size_t)avg_promoted()->average(); | |
259 } | |
260 | |
261 size_t padded_average_promoted_in_bytes() const { | |
262 return (size_t)avg_promoted()->padded_average(); | |
263 } | |
264 | |
265 int change_young_gen_for_maj_pauses() { | |
266 return _change_young_gen_for_maj_pauses; | |
267 } | |
268 void set_change_young_gen_for_maj_pauses(int v) { | |
269 _change_young_gen_for_maj_pauses = v; | |
270 } | |
271 | |
272 int change_old_gen_for_min_pauses() { | |
273 return _change_old_gen_for_min_pauses; | |
274 } | |
275 void set_change_old_gen_for_min_pauses(int v) { | |
276 _change_old_gen_for_min_pauses = v; | |
277 } | |
278 | |
279 // Return true if the old generation size was changed | |
280 // to try to reach a pause time goal. | |
281 bool old_gen_changed_for_pauses() { | |
282 bool result = _change_old_gen_for_maj_pauses != 0 || | |
283 _change_old_gen_for_min_pauses != 0; | |
284 return result; | |
285 } | |
286 | |
287 // Return true if the young generation size was changed | |
288 // to try to reach a pause time goal. | |
289 bool young_gen_changed_for_pauses() { | |
290 bool result = _change_young_gen_for_min_pauses != 0 || | |
291 _change_young_gen_for_maj_pauses != 0; | |
292 return result; | |
293 } | |
294 // end flags for pause goal | |
295 | |
296 // Return true if the old generation size was changed | |
297 // to try to reach a throughput goal. | |
298 bool old_gen_changed_for_throughput() { | |
299 bool result = _change_old_gen_for_throughput != 0; | |
300 return result; | |
301 } | |
302 | |
303 // Return true if the young generation size was changed | |
304 // to try to reach a throughput goal. | |
305 bool young_gen_changed_for_throughput() { | |
306 bool result = _change_young_gen_for_throughput != 0; | |
307 return result; | |
308 } | |
309 | |
310 int decrease_for_footprint() { return _decrease_for_footprint; } | |
311 | |
312 | |
313 // Accessors for estimators. The slope of the linear fit is | |
314 // currently all that is used for making decisions. | |
315 | |
316 LinearLeastSquareFit* major_pause_old_estimator() { | |
317 return _major_pause_old_estimator; | |
318 } | |
319 | |
320 LinearLeastSquareFit* major_pause_young_estimator() { | |
321 return _major_pause_young_estimator; | |
322 } | |
323 | |
324 | |
325 virtual void clear_generation_free_space_flags(); | |
326 | |
327 float major_pause_old_slope() { return _major_pause_old_estimator->slope(); } | |
328 float major_pause_young_slope() { | |
329 return _major_pause_young_estimator->slope(); | |
330 } | |
331 float major_collection_slope() { return _major_collection_estimator->slope();} | |
332 | |
333 bool old_gen_policy_is_ready() { return _old_gen_policy_is_ready; } | |
334 | |
335 // Given the amount of live data in the heap, should we | |
336 // perform a Full GC? | |
337 bool should_full_GC(size_t live_in_old_gen); | |
338 | |
339 // Calculates optimial free space sizes for both the old and young | |
340 // generations. Stores results in _eden_size and _promo_size. | |
341 // Takes current used space in all generations as input, as well | |
342 // as an indication if a full gc has just been performed, for use | |
343 // in deciding if an OOM error should be thrown. | |
344 void compute_generation_free_space(size_t young_live, | |
345 size_t eden_live, | |
346 size_t old_live, | |
347 size_t perm_live, | |
348 size_t cur_eden, // current eden in bytes | |
349 size_t max_old_gen_size, | |
350 size_t max_eden_size, | |
351 bool is_full_gc, | |
1387
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
352 GCCause::Cause gc_cause, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
353 CollectorPolicy* collector_policy); |
0 | 354 |
355 // Calculates new survivor space size; returns a new tenuring threshold | |
356 // value. Stores new survivor size in _survivor_size. | |
357 int compute_survivor_space_size_and_threshold(bool is_survivor_overflow, | |
358 int tenuring_threshold, | |
359 size_t survivor_limit); | |
360 | |
361 // Return the maximum size of a survivor space if the young generation were of | |
362 // size gen_size. | |
363 size_t max_survivor_size(size_t gen_size) { | |
364 // Never allow the target survivor size to grow more than MinSurvivorRatio | |
365 // of the young generation size. We cannot grow into a two semi-space | |
366 // system, with Eden zero sized. Even if the survivor space grows, from() | |
367 // might grow by moving the bottom boundary "down" -- so from space will | |
368 // remain almost full anyway (top() will be near end(), but there will be a | |
369 // large filler object at the bottom). | |
370 const size_t sz = gen_size / MinSurvivorRatio; | |
371 const size_t alignment = _intra_generation_alignment; | |
372 return sz > alignment ? align_size_down(sz, alignment) : alignment; | |
373 } | |
374 | |
375 size_t live_at_last_full_gc() { | |
376 return _live_at_last_full_gc; | |
377 } | |
378 | |
379 size_t bytes_absorbed_from_eden() const { return _bytes_absorbed_from_eden; } | |
380 void reset_bytes_absorbed_from_eden() { _bytes_absorbed_from_eden = 0; } | |
381 | |
382 void set_bytes_absorbed_from_eden(size_t val) { | |
383 _bytes_absorbed_from_eden = val; | |
384 } | |
385 | |
386 // Update averages that are always used (even | |
387 // if adaptive sizing is turned off). | |
388 void update_averages(bool is_survivor_overflow, | |
389 size_t survived, | |
390 size_t promoted); | |
391 | |
392 // Printing support | |
393 virtual bool print_adaptive_size_policy_on(outputStream* st) const; | |
394 }; | |
1972 | 395 |
396 #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSADAPTIVESIZEPOLICY_HPP |