1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,408 @@ 1.4 +/* 1.5 + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSADAPTIVESIZEPOLICY_HPP 1.29 +#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSADAPTIVESIZEPOLICY_HPP 1.30 + 1.31 +#include "gc_implementation/shared/adaptiveSizePolicy.hpp" 1.32 +#include "gc_implementation/shared/gcStats.hpp" 1.33 +#include "gc_implementation/shared/gcUtil.hpp" 1.34 +#include "gc_interface/gcCause.hpp" 1.35 + 1.36 +// This class keeps statistical information and computes the 1.37 +// optimal free space for both the young and old generation 1.38 +// based on current application characteristics (based on gc cost 1.39 +// and application footprint). 1.40 +// 1.41 +// It also computes an optimal tenuring threshold between the young 1.42 +// and old generations, so as to equalize the cost of collections 1.43 +// of those generations, as well as optimial survivor space sizes 1.44 +// for the young generation. 1.45 +// 1.46 +// While this class is specifically intended for a generational system 1.47 +// consisting of a young gen (containing an Eden and two semi-spaces) 1.48 +// and a tenured gen, as well as a perm gen for reflective data, it 1.49 +// makes NO references to specific generations. 1.50 +// 1.51 +// 05/02/2003 Update 1.52 +// The 1.5 policy makes use of data gathered for the costs of GC on 1.53 +// specific generations. That data does reference specific 1.54 +// generation. Also diagnostics specific to generations have 1.55 +// been added. 1.56 + 1.57 +// Forward decls 1.58 +class elapsedTimer; 1.59 + 1.60 +class PSAdaptiveSizePolicy : public AdaptiveSizePolicy { 1.61 + friend class PSGCAdaptivePolicyCounters; 1.62 + private: 1.63 + // These values are used to record decisions made during the 1.64 + // policy. For example, if the young generation was decreased 1.65 + // to decrease the GC cost of minor collections the value 1.66 + // decrease_young_gen_for_throughput_true is used. 1.67 + 1.68 + // Last calculated sizes, in bytes, and aligned 1.69 + // NEEDS_CLEANUP should use sizes.hpp, but it works in ints, not size_t's 1.70 + 1.71 + // Time statistics 1.72 + AdaptivePaddedAverage* _avg_major_pause; 1.73 + 1.74 + // Footprint statistics 1.75 + AdaptiveWeightedAverage* _avg_base_footprint; 1.76 + 1.77 + // Statistical data gathered for GC 1.78 + GCStats _gc_stats; 1.79 + 1.80 + size_t _survivor_size_limit; // Limit in bytes of survivor size 1.81 + const double _collection_cost_margin_fraction; 1.82 + 1.83 + // Variable for estimating the major and minor pause times. 1.84 + // These variables represent linear least-squares fits of 1.85 + // the data. 1.86 + // major pause time vs. old gen size 1.87 + LinearLeastSquareFit* _major_pause_old_estimator; 1.88 + // major pause time vs. young gen size 1.89 + LinearLeastSquareFit* _major_pause_young_estimator; 1.90 + 1.91 + 1.92 + // These record the most recent collection times. They 1.93 + // are available as an alternative to using the averages 1.94 + // for making ergonomic decisions. 1.95 + double _latest_major_mutator_interval_seconds; 1.96 + 1.97 + const size_t _space_alignment; // alignment for eden, survivors 1.98 + 1.99 + const double _gc_minor_pause_goal_sec; // goal for maximum minor gc pause 1.100 + 1.101 + // The amount of live data in the heap at the last full GC, used 1.102 + // as a baseline to help us determine when we need to perform the 1.103 + // next full GC. 1.104 + size_t _live_at_last_full_gc; 1.105 + 1.106 + // decrease/increase the old generation for minor pause time 1.107 + int _change_old_gen_for_min_pauses; 1.108 + 1.109 + // increase/decrease the young generation for major pause time 1.110 + int _change_young_gen_for_maj_pauses; 1.111 + 1.112 + 1.113 + // Flag indicating that the adaptive policy is ready to use 1.114 + bool _old_gen_policy_is_ready; 1.115 + 1.116 + // Changing the generation sizing depends on the data that is 1.117 + // gathered about the effects of changes on the pause times and 1.118 + // throughput. These variable count the number of data points 1.119 + // gathered. The policy may use these counters as a threshhold 1.120 + // for reliable data. 1.121 + julong _young_gen_change_for_major_pause_count; 1.122 + 1.123 + // To facilitate faster growth at start up, supplement the normal 1.124 + // growth percentage for the young gen eden and the 1.125 + // old gen space for promotion with these value which decay 1.126 + // with increasing collections. 1.127 + uint _young_gen_size_increment_supplement; 1.128 + uint _old_gen_size_increment_supplement; 1.129 + 1.130 + // The number of bytes absorbed from eden into the old gen by moving the 1.131 + // boundary over live data. 1.132 + size_t _bytes_absorbed_from_eden; 1.133 + 1.134 + private: 1.135 + 1.136 + // Accessors 1.137 + AdaptivePaddedAverage* avg_major_pause() const { return _avg_major_pause; } 1.138 + double gc_minor_pause_goal_sec() const { return _gc_minor_pause_goal_sec; } 1.139 + 1.140 + // Change the young generation size to achieve a minor GC pause time goal 1.141 + void adjust_promo_for_minor_pause_time(bool is_full_gc, 1.142 + size_t* desired_promo_size_ptr, 1.143 + size_t* desired_eden_size_ptr); 1.144 + void adjust_eden_for_minor_pause_time(bool is_full_gc, 1.145 + size_t* desired_eden_size_ptr); 1.146 + // Change the generation sizes to achieve a GC pause time goal 1.147 + // Returned sizes are not necessarily aligned. 1.148 + void adjust_promo_for_pause_time(bool is_full_gc, 1.149 + size_t* desired_promo_size_ptr, 1.150 + size_t* desired_eden_size_ptr); 1.151 + void adjust_eden_for_pause_time(bool is_full_gc, 1.152 + size_t* desired_promo_size_ptr, 1.153 + size_t* desired_eden_size_ptr); 1.154 + // Change the generation sizes to achieve an application throughput goal 1.155 + // Returned sizes are not necessarily aligned. 1.156 + void adjust_promo_for_throughput(bool is_full_gc, 1.157 + size_t* desired_promo_size_ptr); 1.158 + void adjust_eden_for_throughput(bool is_full_gc, 1.159 + size_t* desired_eden_size_ptr); 1.160 + // Change the generation sizes to achieve minimum footprint 1.161 + // Returned sizes are not aligned. 1.162 + size_t adjust_promo_for_footprint(size_t desired_promo_size, 1.163 + size_t desired_total); 1.164 + size_t adjust_eden_for_footprint(size_t desired_promo_size, 1.165 + size_t desired_total); 1.166 + 1.167 + // Size in bytes for an increment or decrement of eden. 1.168 + virtual size_t eden_increment(size_t cur_eden, uint percent_change); 1.169 + virtual size_t eden_decrement(size_t cur_eden); 1.170 + size_t eden_decrement_aligned_down(size_t cur_eden); 1.171 + size_t eden_increment_with_supplement_aligned_up(size_t cur_eden); 1.172 + 1.173 + // Size in bytes for an increment or decrement of the promotion area 1.174 + virtual size_t promo_increment(size_t cur_promo, uint percent_change); 1.175 + virtual size_t promo_decrement(size_t cur_promo); 1.176 + size_t promo_decrement_aligned_down(size_t cur_promo); 1.177 + size_t promo_increment_with_supplement_aligned_up(size_t cur_promo); 1.178 + 1.179 + // Returns a change that has been scaled down. Result 1.180 + // is not aligned. (If useful, move to some shared 1.181 + // location.) 1.182 + size_t scale_down(size_t change, double part, double total); 1.183 + 1.184 + protected: 1.185 + // Time accessors 1.186 + 1.187 + // Footprint accessors 1.188 + size_t live_space() const { 1.189 + return (size_t)(avg_base_footprint()->average() + 1.190 + avg_young_live()->average() + 1.191 + avg_old_live()->average()); 1.192 + } 1.193 + size_t free_space() const { 1.194 + return _eden_size + _promo_size; 1.195 + } 1.196 + 1.197 + void set_promo_size(size_t new_size) { 1.198 + _promo_size = new_size; 1.199 + } 1.200 + void set_survivor_size(size_t new_size) { 1.201 + _survivor_size = new_size; 1.202 + } 1.203 + 1.204 + // Update estimators 1.205 + void update_minor_pause_old_estimator(double minor_pause_in_ms); 1.206 + 1.207 + virtual GCPolicyKind kind() const { return _gc_ps_adaptive_size_policy; } 1.208 + 1.209 + public: 1.210 + // Use by ASPSYoungGen and ASPSOldGen to limit boundary moving. 1.211 + size_t eden_increment_aligned_up(size_t cur_eden); 1.212 + size_t eden_increment_aligned_down(size_t cur_eden); 1.213 + size_t promo_increment_aligned_up(size_t cur_promo); 1.214 + size_t promo_increment_aligned_down(size_t cur_promo); 1.215 + 1.216 + virtual size_t eden_increment(size_t cur_eden); 1.217 + virtual size_t promo_increment(size_t cur_promo); 1.218 + 1.219 + // Accessors for use by performance counters 1.220 + AdaptivePaddedNoZeroDevAverage* avg_promoted() const { 1.221 + return _gc_stats.avg_promoted(); 1.222 + } 1.223 + AdaptiveWeightedAverage* avg_base_footprint() const { 1.224 + return _avg_base_footprint; 1.225 + } 1.226 + 1.227 + // Input arguments are initial free space sizes for young and old 1.228 + // generations, the initial survivor space size, the 1.229 + // alignment values and the pause & throughput goals. 1.230 + // 1.231 + // NEEDS_CLEANUP this is a singleton object 1.232 + PSAdaptiveSizePolicy(size_t init_eden_size, 1.233 + size_t init_promo_size, 1.234 + size_t init_survivor_size, 1.235 + size_t space_alignment, 1.236 + double gc_pause_goal_sec, 1.237 + double gc_minor_pause_goal_sec, 1.238 + uint gc_time_ratio); 1.239 + 1.240 + // Methods indicating events of interest to the adaptive size policy, 1.241 + // called by GC algorithms. It is the responsibility of users of this 1.242 + // policy to call these methods at the correct times! 1.243 + void major_collection_begin(); 1.244 + void major_collection_end(size_t amount_live, GCCause::Cause gc_cause); 1.245 + 1.246 + void tenured_allocation(size_t size) { 1.247 + _avg_pretenured->sample(size); 1.248 + } 1.249 + 1.250 + // Accessors 1.251 + // NEEDS_CLEANUP should use sizes.hpp 1.252 + 1.253 + static size_t calculate_free_based_on_live(size_t live, uintx ratio_as_percentage); 1.254 + 1.255 + size_t calculated_old_free_size_in_bytes() const; 1.256 + 1.257 + size_t average_old_live_in_bytes() const { 1.258 + return (size_t) avg_old_live()->average(); 1.259 + } 1.260 + 1.261 + size_t average_promoted_in_bytes() const { 1.262 + return (size_t)avg_promoted()->average(); 1.263 + } 1.264 + 1.265 + size_t padded_average_promoted_in_bytes() const { 1.266 + return (size_t)avg_promoted()->padded_average(); 1.267 + } 1.268 + 1.269 + int change_young_gen_for_maj_pauses() { 1.270 + return _change_young_gen_for_maj_pauses; 1.271 + } 1.272 + void set_change_young_gen_for_maj_pauses(int v) { 1.273 + _change_young_gen_for_maj_pauses = v; 1.274 + } 1.275 + 1.276 + int change_old_gen_for_min_pauses() { 1.277 + return _change_old_gen_for_min_pauses; 1.278 + } 1.279 + void set_change_old_gen_for_min_pauses(int v) { 1.280 + _change_old_gen_for_min_pauses = v; 1.281 + } 1.282 + 1.283 + // Return true if the old generation size was changed 1.284 + // to try to reach a pause time goal. 1.285 + bool old_gen_changed_for_pauses() { 1.286 + bool result = _change_old_gen_for_maj_pauses != 0 || 1.287 + _change_old_gen_for_min_pauses != 0; 1.288 + return result; 1.289 + } 1.290 + 1.291 + // Return true if the young generation size was changed 1.292 + // to try to reach a pause time goal. 1.293 + bool young_gen_changed_for_pauses() { 1.294 + bool result = _change_young_gen_for_min_pauses != 0 || 1.295 + _change_young_gen_for_maj_pauses != 0; 1.296 + return result; 1.297 + } 1.298 + // end flags for pause goal 1.299 + 1.300 + // Return true if the old generation size was changed 1.301 + // to try to reach a throughput goal. 1.302 + bool old_gen_changed_for_throughput() { 1.303 + bool result = _change_old_gen_for_throughput != 0; 1.304 + return result; 1.305 + } 1.306 + 1.307 + // Return true if the young generation size was changed 1.308 + // to try to reach a throughput goal. 1.309 + bool young_gen_changed_for_throughput() { 1.310 + bool result = _change_young_gen_for_throughput != 0; 1.311 + return result; 1.312 + } 1.313 + 1.314 + int decrease_for_footprint() { return _decrease_for_footprint; } 1.315 + 1.316 + 1.317 + // Accessors for estimators. The slope of the linear fit is 1.318 + // currently all that is used for making decisions. 1.319 + 1.320 + LinearLeastSquareFit* major_pause_old_estimator() { 1.321 + return _major_pause_old_estimator; 1.322 + } 1.323 + 1.324 + LinearLeastSquareFit* major_pause_young_estimator() { 1.325 + return _major_pause_young_estimator; 1.326 + } 1.327 + 1.328 + 1.329 + virtual void clear_generation_free_space_flags(); 1.330 + 1.331 + float major_pause_old_slope() { return _major_pause_old_estimator->slope(); } 1.332 + float major_pause_young_slope() { 1.333 + return _major_pause_young_estimator->slope(); 1.334 + } 1.335 + float major_collection_slope() { return _major_collection_estimator->slope();} 1.336 + 1.337 + bool old_gen_policy_is_ready() { return _old_gen_policy_is_ready; } 1.338 + 1.339 + // Given the amount of live data in the heap, should we 1.340 + // perform a Full GC? 1.341 + bool should_full_GC(size_t live_in_old_gen); 1.342 + 1.343 + // Calculates optimal (free) space sizes for both the young and old 1.344 + // generations. Stores results in _eden_size and _promo_size. 1.345 + // Takes current used space in all generations as input, as well 1.346 + // as an indication if a full gc has just been performed, for use 1.347 + // in deciding if an OOM error should be thrown. 1.348 + void compute_generations_free_space(size_t young_live, 1.349 + size_t eden_live, 1.350 + size_t old_live, 1.351 + size_t cur_eden, // current eden in bytes 1.352 + size_t max_old_gen_size, 1.353 + size_t max_eden_size, 1.354 + bool is_full_gc); 1.355 + 1.356 + void compute_eden_space_size(size_t young_live, 1.357 + size_t eden_live, 1.358 + size_t cur_eden, // current eden in bytes 1.359 + size_t max_eden_size, 1.360 + bool is_full_gc); 1.361 + 1.362 + void compute_old_gen_free_space(size_t old_live, 1.363 + size_t cur_eden, // current eden in bytes 1.364 + size_t max_old_gen_size, 1.365 + bool is_full_gc); 1.366 + 1.367 + // Calculates new survivor space size; returns a new tenuring threshold 1.368 + // value. Stores new survivor size in _survivor_size. 1.369 + uint compute_survivor_space_size_and_threshold(bool is_survivor_overflow, 1.370 + uint tenuring_threshold, 1.371 + size_t survivor_limit); 1.372 + 1.373 + // Return the maximum size of a survivor space if the young generation were of 1.374 + // size gen_size. 1.375 + size_t max_survivor_size(size_t gen_size) { 1.376 + // Never allow the target survivor size to grow more than MinSurvivorRatio 1.377 + // of the young generation size. We cannot grow into a two semi-space 1.378 + // system, with Eden zero sized. Even if the survivor space grows, from() 1.379 + // might grow by moving the bottom boundary "down" -- so from space will 1.380 + // remain almost full anyway (top() will be near end(), but there will be a 1.381 + // large filler object at the bottom). 1.382 + const size_t sz = gen_size / MinSurvivorRatio; 1.383 + const size_t alignment = _space_alignment; 1.384 + return sz > alignment ? align_size_down(sz, alignment) : alignment; 1.385 + } 1.386 + 1.387 + size_t live_at_last_full_gc() { 1.388 + return _live_at_last_full_gc; 1.389 + } 1.390 + 1.391 + size_t bytes_absorbed_from_eden() const { return _bytes_absorbed_from_eden; } 1.392 + void reset_bytes_absorbed_from_eden() { _bytes_absorbed_from_eden = 0; } 1.393 + 1.394 + void set_bytes_absorbed_from_eden(size_t val) { 1.395 + _bytes_absorbed_from_eden = val; 1.396 + } 1.397 + 1.398 + // Update averages that are always used (even 1.399 + // if adaptive sizing is turned off). 1.400 + void update_averages(bool is_survivor_overflow, 1.401 + size_t survived, 1.402 + size_t promoted); 1.403 + 1.404 + // Printing support 1.405 + virtual bool print_adaptive_size_policy_on(outputStream* st) const; 1.406 + 1.407 + // Decay the supplemental growth additive. 1.408 + void decay_supplemental_growth(bool is_full_gc); 1.409 +}; 1.410 + 1.411 +#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSADAPTIVESIZEPOLICY_HPP