1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,1334 @@ 1.4 +/* 1.5 + * Copyright 2004-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 +#include "incls/_precompiled.incl" 1.28 +#include "incls/_cmsAdaptiveSizePolicy.cpp.incl" 1.29 + 1.30 +elapsedTimer CMSAdaptiveSizePolicy::_concurrent_timer; 1.31 +elapsedTimer CMSAdaptiveSizePolicy::_STW_timer; 1.32 + 1.33 +// Defined if the granularity of the time measurements is potentially too large. 1.34 +#define CLOCK_GRANULARITY_TOO_LARGE 1.35 + 1.36 +CMSAdaptiveSizePolicy::CMSAdaptiveSizePolicy(size_t init_eden_size, 1.37 + size_t init_promo_size, 1.38 + size_t init_survivor_size, 1.39 + double max_gc_minor_pause_sec, 1.40 + double max_gc_pause_sec, 1.41 + uint gc_cost_ratio) : 1.42 + AdaptiveSizePolicy(init_eden_size, 1.43 + init_promo_size, 1.44 + init_survivor_size, 1.45 + max_gc_pause_sec, 1.46 + gc_cost_ratio) { 1.47 + 1.48 + clear_internal_time_intervals(); 1.49 + 1.50 + _processor_count = os::active_processor_count(); 1.51 + 1.52 + if (CMSConcurrentMTEnabled && (ParallelCMSThreads > 1)) { 1.53 + assert(_processor_count > 0, "Processor count is suspect"); 1.54 + _concurrent_processor_count = MIN2((uint) ParallelCMSThreads, 1.55 + (uint) _processor_count); 1.56 + } else { 1.57 + _concurrent_processor_count = 1; 1.58 + } 1.59 + 1.60 + _avg_concurrent_time = new AdaptiveWeightedAverage(AdaptiveTimeWeight); 1.61 + _avg_concurrent_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight); 1.62 + _avg_concurrent_gc_cost = new AdaptiveWeightedAverage(AdaptiveTimeWeight); 1.63 + 1.64 + _avg_initial_pause = new AdaptivePaddedAverage(AdaptiveTimeWeight, 1.65 + PausePadding); 1.66 + _avg_remark_pause = new AdaptivePaddedAverage(AdaptiveTimeWeight, 1.67 + PausePadding); 1.68 + 1.69 + _avg_cms_STW_time = new AdaptiveWeightedAverage(AdaptiveTimeWeight); 1.70 + _avg_cms_STW_gc_cost = new AdaptiveWeightedAverage(AdaptiveTimeWeight); 1.71 + 1.72 + _avg_cms_free = new AdaptiveWeightedAverage(AdaptiveTimeWeight); 1.73 + _avg_cms_free_at_sweep = new AdaptiveWeightedAverage(AdaptiveTimeWeight); 1.74 + _avg_cms_promo = new AdaptiveWeightedAverage(AdaptiveTimeWeight); 1.75 + 1.76 + // Mark-sweep-compact 1.77 + _avg_msc_pause = new AdaptiveWeightedAverage(AdaptiveTimeWeight); 1.78 + _avg_msc_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight); 1.79 + _avg_msc_gc_cost = new AdaptiveWeightedAverage(AdaptiveTimeWeight); 1.80 + 1.81 + // Mark-sweep 1.82 + _avg_ms_pause = new AdaptiveWeightedAverage(AdaptiveTimeWeight); 1.83 + _avg_ms_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight); 1.84 + _avg_ms_gc_cost = new AdaptiveWeightedAverage(AdaptiveTimeWeight); 1.85 + 1.86 + // Variables that estimate pause times as a function of generation 1.87 + // size. 1.88 + _remark_pause_old_estimator = 1.89 + new LinearLeastSquareFit(AdaptiveSizePolicyWeight); 1.90 + _initial_pause_old_estimator = 1.91 + new LinearLeastSquareFit(AdaptiveSizePolicyWeight); 1.92 + _remark_pause_young_estimator = 1.93 + new LinearLeastSquareFit(AdaptiveSizePolicyWeight); 1.94 + _initial_pause_young_estimator = 1.95 + new LinearLeastSquareFit(AdaptiveSizePolicyWeight); 1.96 + 1.97 + // Alignment comes from that used in ReservedSpace. 1.98 + _generation_alignment = os::vm_allocation_granularity(); 1.99 + 1.100 + // Start the concurrent timer here so that the first 1.101 + // concurrent_phases_begin() measures a finite mutator 1.102 + // time. A finite mutator time is used to determine 1.103 + // if a concurrent collection has been started. If this 1.104 + // proves to be a problem, use some explicit flag to 1.105 + // signal that a concurrent collection has been started. 1.106 + _concurrent_timer.start(); 1.107 + _STW_timer.start(); 1.108 +} 1.109 + 1.110 +double CMSAdaptiveSizePolicy::concurrent_processor_fraction() { 1.111 + // For now assume no other daemon threads are taking alway 1.112 + // cpu's from the application. 1.113 + return ((double) _concurrent_processor_count / (double) _processor_count); 1.114 +} 1.115 + 1.116 +double CMSAdaptiveSizePolicy::concurrent_collection_cost( 1.117 + double interval_in_seconds) { 1.118 + // When the precleaning and sweeping phases use multiple 1.119 + // threads, change one_processor_fraction to 1.120 + // concurrent_processor_fraction(). 1.121 + double one_processor_fraction = 1.0 / ((double) processor_count()); 1.122 + double concurrent_cost = 1.123 + collection_cost(_latest_cms_concurrent_marking_time_secs, 1.124 + interval_in_seconds) * concurrent_processor_fraction() + 1.125 + collection_cost(_latest_cms_concurrent_precleaning_time_secs, 1.126 + interval_in_seconds) * one_processor_fraction + 1.127 + collection_cost(_latest_cms_concurrent_sweeping_time_secs, 1.128 + interval_in_seconds) * one_processor_fraction; 1.129 + if (PrintAdaptiveSizePolicy && Verbose) { 1.130 + gclog_or_tty->print_cr( 1.131 + "\nCMSAdaptiveSizePolicy::scaled_concurrent_collection_cost(%f) " 1.132 + "_latest_cms_concurrent_marking_cost %f " 1.133 + "_latest_cms_concurrent_precleaning_cost %f " 1.134 + "_latest_cms_concurrent_sweeping_cost %f " 1.135 + "concurrent_processor_fraction %f " 1.136 + "concurrent_cost %f ", 1.137 + interval_in_seconds, 1.138 + collection_cost(_latest_cms_concurrent_marking_time_secs, 1.139 + interval_in_seconds), 1.140 + collection_cost(_latest_cms_concurrent_precleaning_time_secs, 1.141 + interval_in_seconds), 1.142 + collection_cost(_latest_cms_concurrent_sweeping_time_secs, 1.143 + interval_in_seconds), 1.144 + concurrent_processor_fraction(), 1.145 + concurrent_cost); 1.146 + } 1.147 + return concurrent_cost; 1.148 +} 1.149 + 1.150 +double CMSAdaptiveSizePolicy::concurrent_collection_time() { 1.151 + double latest_cms_sum_concurrent_phases_time_secs = 1.152 + _latest_cms_concurrent_marking_time_secs + 1.153 + _latest_cms_concurrent_precleaning_time_secs + 1.154 + _latest_cms_concurrent_sweeping_time_secs; 1.155 + return latest_cms_sum_concurrent_phases_time_secs; 1.156 +} 1.157 + 1.158 +double CMSAdaptiveSizePolicy::scaled_concurrent_collection_time() { 1.159 + // When the precleaning and sweeping phases use multiple 1.160 + // threads, change one_processor_fraction to 1.161 + // concurrent_processor_fraction(). 1.162 + double one_processor_fraction = 1.0 / ((double) processor_count()); 1.163 + double latest_cms_sum_concurrent_phases_time_secs = 1.164 + _latest_cms_concurrent_marking_time_secs * concurrent_processor_fraction() + 1.165 + _latest_cms_concurrent_precleaning_time_secs * one_processor_fraction + 1.166 + _latest_cms_concurrent_sweeping_time_secs * one_processor_fraction ; 1.167 + if (PrintAdaptiveSizePolicy && Verbose) { 1.168 + gclog_or_tty->print_cr( 1.169 + "\nCMSAdaptiveSizePolicy::scaled_concurrent_collection_time " 1.170 + "_latest_cms_concurrent_marking_time_secs %f " 1.171 + "_latest_cms_concurrent_precleaning_time_secs %f " 1.172 + "_latest_cms_concurrent_sweeping_time_secs %f " 1.173 + "concurrent_processor_fraction %f " 1.174 + "latest_cms_sum_concurrent_phases_time_secs %f ", 1.175 + _latest_cms_concurrent_marking_time_secs, 1.176 + _latest_cms_concurrent_precleaning_time_secs, 1.177 + _latest_cms_concurrent_sweeping_time_secs, 1.178 + concurrent_processor_fraction(), 1.179 + latest_cms_sum_concurrent_phases_time_secs); 1.180 + } 1.181 + return latest_cms_sum_concurrent_phases_time_secs; 1.182 +} 1.183 + 1.184 +void CMSAdaptiveSizePolicy::update_minor_pause_old_estimator( 1.185 + double minor_pause_in_ms) { 1.186 + // Get the equivalent of the free space 1.187 + // that is available for promotions in the CMS generation 1.188 + // and use that to update _minor_pause_old_estimator 1.189 + 1.190 + // Don't implement this until it is needed. A warning is 1.191 + // printed if _minor_pause_old_estimator is used. 1.192 +} 1.193 + 1.194 +void CMSAdaptiveSizePolicy::concurrent_marking_begin() { 1.195 + if (PrintAdaptiveSizePolicy && Verbose) { 1.196 + gclog_or_tty->print(" "); 1.197 + gclog_or_tty->stamp(); 1.198 + gclog_or_tty->print(": concurrent_marking_begin "); 1.199 + } 1.200 + // Update the interval time 1.201 + _concurrent_timer.stop(); 1.202 + _latest_cms_collection_end_to_collection_start_secs = _concurrent_timer.seconds(); 1.203 + if (PrintAdaptiveSizePolicy && Verbose) { 1.204 + gclog_or_tty->print_cr("CMSAdaptiveSizePolicy::concurrent_marking_begin: " 1.205 + "mutator time %f", _latest_cms_collection_end_to_collection_start_secs); 1.206 + } 1.207 + _concurrent_timer.reset(); 1.208 + _concurrent_timer.start(); 1.209 +} 1.210 + 1.211 +void CMSAdaptiveSizePolicy::concurrent_marking_end() { 1.212 + if (PrintAdaptiveSizePolicy && Verbose) { 1.213 + gclog_or_tty->stamp(); 1.214 + gclog_or_tty->print_cr("CMSAdaptiveSizePolicy::concurrent_marking_end()"); 1.215 + } 1.216 + 1.217 + _concurrent_timer.stop(); 1.218 + _latest_cms_concurrent_marking_time_secs = _concurrent_timer.seconds(); 1.219 + 1.220 + if (PrintAdaptiveSizePolicy && Verbose) { 1.221 + gclog_or_tty->print_cr("\n CMSAdaptiveSizePolicy::concurrent_marking_end" 1.222 + ":concurrent marking time (s) %f", 1.223 + _latest_cms_concurrent_marking_time_secs); 1.224 + } 1.225 +} 1.226 + 1.227 +void CMSAdaptiveSizePolicy::concurrent_precleaning_begin() { 1.228 + if (PrintAdaptiveSizePolicy && Verbose) { 1.229 + gclog_or_tty->stamp(); 1.230 + gclog_or_tty->print_cr( 1.231 + "CMSAdaptiveSizePolicy::concurrent_precleaning_begin()"); 1.232 + } 1.233 + _concurrent_timer.reset(); 1.234 + _concurrent_timer.start(); 1.235 +} 1.236 + 1.237 + 1.238 +void CMSAdaptiveSizePolicy::concurrent_precleaning_end() { 1.239 + if (PrintAdaptiveSizePolicy && Verbose) { 1.240 + gclog_or_tty->stamp(); 1.241 + gclog_or_tty->print_cr("CMSAdaptiveSizePolicy::concurrent_precleaning_end()"); 1.242 + } 1.243 + 1.244 + _concurrent_timer.stop(); 1.245 + // May be set again by a second call during the same collection. 1.246 + _latest_cms_concurrent_precleaning_time_secs = _concurrent_timer.seconds(); 1.247 + 1.248 + if (PrintAdaptiveSizePolicy && Verbose) { 1.249 + gclog_or_tty->print_cr("\n CMSAdaptiveSizePolicy::concurrent_precleaning_end" 1.250 + ":concurrent precleaning time (s) %f", 1.251 + _latest_cms_concurrent_precleaning_time_secs); 1.252 + } 1.253 +} 1.254 + 1.255 +void CMSAdaptiveSizePolicy::concurrent_sweeping_begin() { 1.256 + if (PrintAdaptiveSizePolicy && Verbose) { 1.257 + gclog_or_tty->stamp(); 1.258 + gclog_or_tty->print_cr( 1.259 + "CMSAdaptiveSizePolicy::concurrent_sweeping_begin()"); 1.260 + } 1.261 + _concurrent_timer.reset(); 1.262 + _concurrent_timer.start(); 1.263 +} 1.264 + 1.265 + 1.266 +void CMSAdaptiveSizePolicy::concurrent_sweeping_end() { 1.267 + if (PrintAdaptiveSizePolicy && Verbose) { 1.268 + gclog_or_tty->stamp(); 1.269 + gclog_or_tty->print_cr("CMSAdaptiveSizePolicy::concurrent_sweeping_end()"); 1.270 + } 1.271 + 1.272 + _concurrent_timer.stop(); 1.273 + _latest_cms_concurrent_sweeping_time_secs = _concurrent_timer.seconds(); 1.274 + 1.275 + if (PrintAdaptiveSizePolicy && Verbose) { 1.276 + gclog_or_tty->print_cr("\n CMSAdaptiveSizePolicy::concurrent_sweeping_end" 1.277 + ":concurrent sweeping time (s) %f", 1.278 + _latest_cms_concurrent_sweeping_time_secs); 1.279 + } 1.280 +} 1.281 + 1.282 +void CMSAdaptiveSizePolicy::concurrent_phases_end(GCCause::Cause gc_cause, 1.283 + size_t cur_eden, 1.284 + size_t cur_promo) { 1.285 + if (PrintAdaptiveSizePolicy && Verbose) { 1.286 + gclog_or_tty->print(" "); 1.287 + gclog_or_tty->stamp(); 1.288 + gclog_or_tty->print(": concurrent_phases_end "); 1.289 + } 1.290 + 1.291 + // Update the concurrent timer 1.292 + _concurrent_timer.stop(); 1.293 + 1.294 + if (gc_cause != GCCause::_java_lang_system_gc || 1.295 + UseAdaptiveSizePolicyWithSystemGC) { 1.296 + 1.297 + avg_cms_free()->sample(cur_promo); 1.298 + double latest_cms_sum_concurrent_phases_time_secs = 1.299 + concurrent_collection_time(); 1.300 + 1.301 + _avg_concurrent_time->sample(latest_cms_sum_concurrent_phases_time_secs); 1.302 + 1.303 + // Cost of collection (unit-less) 1.304 + 1.305 + // Total interval for collection. May not be valid. Tests 1.306 + // below determine whether to use this. 1.307 + // 1.308 + if (PrintAdaptiveSizePolicy && Verbose) { 1.309 + gclog_or_tty->print_cr("\nCMSAdaptiveSizePolicy::concurrent_phases_end \n" 1.310 + "_latest_cms_reset_end_to_initial_mark_start_secs %f \n" 1.311 + "_latest_cms_initial_mark_start_to_end_time_secs %f \n" 1.312 + "_latest_cms_remark_start_to_end_time_secs %f \n" 1.313 + "_latest_cms_concurrent_marking_time_secs %f \n" 1.314 + "_latest_cms_concurrent_precleaning_time_secs %f \n" 1.315 + "_latest_cms_concurrent_sweeping_time_secs %f \n" 1.316 + "latest_cms_sum_concurrent_phases_time_secs %f \n" 1.317 + "_latest_cms_collection_end_to_collection_start_secs %f \n" 1.318 + "concurrent_processor_fraction %f", 1.319 + _latest_cms_reset_end_to_initial_mark_start_secs, 1.320 + _latest_cms_initial_mark_start_to_end_time_secs, 1.321 + _latest_cms_remark_start_to_end_time_secs, 1.322 + _latest_cms_concurrent_marking_time_secs, 1.323 + _latest_cms_concurrent_precleaning_time_secs, 1.324 + _latest_cms_concurrent_sweeping_time_secs, 1.325 + latest_cms_sum_concurrent_phases_time_secs, 1.326 + _latest_cms_collection_end_to_collection_start_secs, 1.327 + concurrent_processor_fraction()); 1.328 + } 1.329 + double interval_in_seconds = 1.330 + _latest_cms_initial_mark_start_to_end_time_secs + 1.331 + _latest_cms_remark_start_to_end_time_secs + 1.332 + latest_cms_sum_concurrent_phases_time_secs + 1.333 + _latest_cms_collection_end_to_collection_start_secs; 1.334 + assert(interval_in_seconds >= 0.0, 1.335 + "Bad interval between cms collections"); 1.336 + 1.337 + // Sample for performance counter 1.338 + avg_concurrent_interval()->sample(interval_in_seconds); 1.339 + 1.340 + // STW costs (initial and remark pauses) 1.341 + // Cost of collection (unit-less) 1.342 + assert(_latest_cms_initial_mark_start_to_end_time_secs >= 0.0, 1.343 + "Bad initial mark pause"); 1.344 + assert(_latest_cms_remark_start_to_end_time_secs >= 0.0, 1.345 + "Bad remark pause"); 1.346 + double STW_time_in_seconds = 1.347 + _latest_cms_initial_mark_start_to_end_time_secs + 1.348 + _latest_cms_remark_start_to_end_time_secs; 1.349 + double STW_collection_cost = 0.0; 1.350 + if (interval_in_seconds > 0.0) { 1.351 + // cost for the STW phases of the concurrent collection. 1.352 + STW_collection_cost = STW_time_in_seconds / interval_in_seconds; 1.353 + avg_cms_STW_gc_cost()->sample(STW_collection_cost); 1.354 + } 1.355 + if (PrintAdaptiveSizePolicy && Verbose) { 1.356 + gclog_or_tty->print("cmsAdaptiveSizePolicy::STW_collection_end: " 1.357 + "STW gc cost: %f average: %f", STW_collection_cost, 1.358 + avg_cms_STW_gc_cost()->average()); 1.359 + gclog_or_tty->print_cr(" STW pause: %f (ms) STW period %f (ms)", 1.360 + (double) STW_time_in_seconds * MILLIUNITS, 1.361 + (double) interval_in_seconds * MILLIUNITS); 1.362 + } 1.363 + 1.364 + double concurrent_cost = 0.0; 1.365 + if (latest_cms_sum_concurrent_phases_time_secs > 0.0) { 1.366 + concurrent_cost = concurrent_collection_cost(interval_in_seconds); 1.367 + 1.368 + avg_concurrent_gc_cost()->sample(concurrent_cost); 1.369 + // Average this ms cost into all the other types gc costs 1.370 + 1.371 + if (PrintAdaptiveSizePolicy && Verbose) { 1.372 + gclog_or_tty->print("cmsAdaptiveSizePolicy::concurrent_phases_end: " 1.373 + "concurrent gc cost: %f average: %f", 1.374 + concurrent_cost, 1.375 + _avg_concurrent_gc_cost->average()); 1.376 + gclog_or_tty->print_cr(" concurrent time: %f (ms) cms period %f (ms)" 1.377 + " processor fraction: %f", 1.378 + latest_cms_sum_concurrent_phases_time_secs * MILLIUNITS, 1.379 + interval_in_seconds * MILLIUNITS, 1.380 + concurrent_processor_fraction()); 1.381 + } 1.382 + } 1.383 + double total_collection_cost = STW_collection_cost + concurrent_cost; 1.384 + avg_major_gc_cost()->sample(total_collection_cost); 1.385 + 1.386 + // Gather information for estimating future behavior 1.387 + double initial_pause_in_ms = _latest_cms_initial_mark_start_to_end_time_secs * MILLIUNITS; 1.388 + double remark_pause_in_ms = _latest_cms_remark_start_to_end_time_secs * MILLIUNITS; 1.389 + 1.390 + double cur_promo_size_in_mbytes = ((double)cur_promo)/((double)M); 1.391 + initial_pause_old_estimator()->update(cur_promo_size_in_mbytes, 1.392 + initial_pause_in_ms); 1.393 + remark_pause_old_estimator()->update(cur_promo_size_in_mbytes, 1.394 + remark_pause_in_ms); 1.395 + major_collection_estimator()->update(cur_promo_size_in_mbytes, 1.396 + total_collection_cost); 1.397 + 1.398 + // This estimate uses the average eden size. It could also 1.399 + // have used the latest eden size. Which is better? 1.400 + double cur_eden_size_in_mbytes = ((double)cur_eden)/((double) M); 1.401 + initial_pause_young_estimator()->update(cur_eden_size_in_mbytes, 1.402 + initial_pause_in_ms); 1.403 + remark_pause_young_estimator()->update(cur_eden_size_in_mbytes, 1.404 + remark_pause_in_ms); 1.405 + } 1.406 + 1.407 + clear_internal_time_intervals(); 1.408 + 1.409 + set_first_after_collection(); 1.410 + 1.411 + // The concurrent phases keeps track of it's own mutator interval 1.412 + // with this timer. This allows the stop-the-world phase to 1.413 + // be included in the mutator time so that the stop-the-world time 1.414 + // is not double counted. Reset and start it. 1.415 + _concurrent_timer.reset(); 1.416 + _concurrent_timer.start(); 1.417 + 1.418 + // The mutator time between STW phases does not include the 1.419 + // concurrent collection time. 1.420 + _STW_timer.reset(); 1.421 + _STW_timer.start(); 1.422 +} 1.423 + 1.424 +void CMSAdaptiveSizePolicy::checkpoint_roots_initial_begin() { 1.425 + // Update the interval time 1.426 + _STW_timer.stop(); 1.427 + _latest_cms_reset_end_to_initial_mark_start_secs = _STW_timer.seconds(); 1.428 + // Reset for the initial mark 1.429 + _STW_timer.reset(); 1.430 + _STW_timer.start(); 1.431 +} 1.432 + 1.433 +void CMSAdaptiveSizePolicy::checkpoint_roots_initial_end( 1.434 + GCCause::Cause gc_cause) { 1.435 + _STW_timer.stop(); 1.436 + 1.437 + if (gc_cause != GCCause::_java_lang_system_gc || 1.438 + UseAdaptiveSizePolicyWithSystemGC) { 1.439 + _latest_cms_initial_mark_start_to_end_time_secs = _STW_timer.seconds(); 1.440 + avg_initial_pause()->sample(_latest_cms_initial_mark_start_to_end_time_secs); 1.441 + 1.442 + if (PrintAdaptiveSizePolicy && Verbose) { 1.443 + gclog_or_tty->print( 1.444 + "cmsAdaptiveSizePolicy::checkpoint_roots_initial_end: " 1.445 + "initial pause: %f ", _latest_cms_initial_mark_start_to_end_time_secs); 1.446 + } 1.447 + } 1.448 + 1.449 + _STW_timer.reset(); 1.450 + _STW_timer.start(); 1.451 +} 1.452 + 1.453 +void CMSAdaptiveSizePolicy::checkpoint_roots_final_begin() { 1.454 + _STW_timer.stop(); 1.455 + _latest_cms_initial_mark_end_to_remark_start_secs = _STW_timer.seconds(); 1.456 + // Start accumumlating time for the remark in the STW timer. 1.457 + _STW_timer.reset(); 1.458 + _STW_timer.start(); 1.459 +} 1.460 + 1.461 +void CMSAdaptiveSizePolicy::checkpoint_roots_final_end( 1.462 + GCCause::Cause gc_cause) { 1.463 + _STW_timer.stop(); 1.464 + if (gc_cause != GCCause::_java_lang_system_gc || 1.465 + UseAdaptiveSizePolicyWithSystemGC) { 1.466 + // Total initial mark pause + remark pause. 1.467 + _latest_cms_remark_start_to_end_time_secs = _STW_timer.seconds(); 1.468 + double STW_time_in_seconds = _latest_cms_initial_mark_start_to_end_time_secs + 1.469 + _latest_cms_remark_start_to_end_time_secs; 1.470 + double STW_time_in_ms = STW_time_in_seconds * MILLIUNITS; 1.471 + 1.472 + avg_remark_pause()->sample(_latest_cms_remark_start_to_end_time_secs); 1.473 + 1.474 + // Sample total for initial mark + remark 1.475 + avg_cms_STW_time()->sample(STW_time_in_seconds); 1.476 + 1.477 + if (PrintAdaptiveSizePolicy && Verbose) { 1.478 + gclog_or_tty->print("cmsAdaptiveSizePolicy::checkpoint_roots_final_end: " 1.479 + "remark pause: %f", _latest_cms_remark_start_to_end_time_secs); 1.480 + } 1.481 + 1.482 + } 1.483 + // Don't start the STW times here because the concurrent 1.484 + // sweep and reset has not happened. 1.485 + // Keep the old comment above in case I don't understand 1.486 + // what is going on but now 1.487 + // Start the STW timer because it is used by ms_collection_begin() 1.488 + // and ms_collection_end() to get the sweep time if a MS is being 1.489 + // done in the foreground. 1.490 + _STW_timer.reset(); 1.491 + _STW_timer.start(); 1.492 +} 1.493 + 1.494 +void CMSAdaptiveSizePolicy::msc_collection_begin() { 1.495 + if (PrintAdaptiveSizePolicy && Verbose) { 1.496 + gclog_or_tty->print(" "); 1.497 + gclog_or_tty->stamp(); 1.498 + gclog_or_tty->print(": msc_collection_begin "); 1.499 + } 1.500 + _STW_timer.stop(); 1.501 + _latest_cms_msc_end_to_msc_start_time_secs = _STW_timer.seconds(); 1.502 + if (PrintAdaptiveSizePolicy && Verbose) { 1.503 + gclog_or_tty->print_cr("CMSAdaptiveSizePolicy::msc_collection_begin: " 1.504 + "mutator time %f", 1.505 + _latest_cms_msc_end_to_msc_start_time_secs); 1.506 + } 1.507 + avg_msc_interval()->sample(_latest_cms_msc_end_to_msc_start_time_secs); 1.508 + _STW_timer.reset(); 1.509 + _STW_timer.start(); 1.510 +} 1.511 + 1.512 +void CMSAdaptiveSizePolicy::msc_collection_end(GCCause::Cause gc_cause) { 1.513 + if (PrintAdaptiveSizePolicy && Verbose) { 1.514 + gclog_or_tty->print(" "); 1.515 + gclog_or_tty->stamp(); 1.516 + gclog_or_tty->print(": msc_collection_end "); 1.517 + } 1.518 + _STW_timer.stop(); 1.519 + if (gc_cause != GCCause::_java_lang_system_gc || 1.520 + UseAdaptiveSizePolicyWithSystemGC) { 1.521 + double msc_pause_in_seconds = _STW_timer.seconds(); 1.522 + if ((_latest_cms_msc_end_to_msc_start_time_secs > 0.0) && 1.523 + (msc_pause_in_seconds > 0.0)) { 1.524 + avg_msc_pause()->sample(msc_pause_in_seconds); 1.525 + double mutator_time_in_seconds = 0.0; 1.526 + if (_latest_cms_collection_end_to_collection_start_secs == 0.0) { 1.527 + // This assertion may fail because of time stamp gradularity. 1.528 + // Comment it out and investiage it at a later time. The large 1.529 + // time stamp granularity occurs on some older linux systems. 1.530 +#ifndef CLOCK_GRANULARITY_TOO_LARGE 1.531 + assert((_latest_cms_concurrent_marking_time_secs == 0.0) && 1.532 + (_latest_cms_concurrent_precleaning_time_secs == 0.0) && 1.533 + (_latest_cms_concurrent_sweeping_time_secs == 0.0), 1.534 + "There should not be any concurrent time"); 1.535 +#endif 1.536 + // A concurrent collection did not start. Mutator time 1.537 + // between collections comes from the STW MSC timer. 1.538 + mutator_time_in_seconds = _latest_cms_msc_end_to_msc_start_time_secs; 1.539 + } else { 1.540 + // The concurrent collection did start so count the mutator 1.541 + // time to the start of the concurrent collection. In this 1.542 + // case the _latest_cms_msc_end_to_msc_start_time_secs measures 1.543 + // the time between the initial mark or remark and the 1.544 + // start of the MSC. That has no real meaning. 1.545 + mutator_time_in_seconds = _latest_cms_collection_end_to_collection_start_secs; 1.546 + } 1.547 + 1.548 + double latest_cms_sum_concurrent_phases_time_secs = 1.549 + concurrent_collection_time(); 1.550 + double interval_in_seconds = 1.551 + mutator_time_in_seconds + 1.552 + _latest_cms_initial_mark_start_to_end_time_secs + 1.553 + _latest_cms_remark_start_to_end_time_secs + 1.554 + latest_cms_sum_concurrent_phases_time_secs + 1.555 + msc_pause_in_seconds; 1.556 + 1.557 + if (PrintAdaptiveSizePolicy && Verbose) { 1.558 + gclog_or_tty->print_cr(" interval_in_seconds %f \n" 1.559 + " mutator_time_in_seconds %f \n" 1.560 + " _latest_cms_initial_mark_start_to_end_time_secs %f\n" 1.561 + " _latest_cms_remark_start_to_end_time_secs %f\n" 1.562 + " latest_cms_sum_concurrent_phases_time_secs %f\n" 1.563 + " msc_pause_in_seconds %f\n", 1.564 + interval_in_seconds, 1.565 + mutator_time_in_seconds, 1.566 + _latest_cms_initial_mark_start_to_end_time_secs, 1.567 + _latest_cms_remark_start_to_end_time_secs, 1.568 + latest_cms_sum_concurrent_phases_time_secs, 1.569 + msc_pause_in_seconds); 1.570 + } 1.571 + 1.572 + // The concurrent cost is wasted cost but it should be 1.573 + // included. 1.574 + double concurrent_cost = concurrent_collection_cost(interval_in_seconds); 1.575 + 1.576 + // Initial mark and remark, also wasted. 1.577 + double STW_time_in_seconds = _latest_cms_initial_mark_start_to_end_time_secs + 1.578 + _latest_cms_remark_start_to_end_time_secs; 1.579 + double STW_collection_cost = 1.580 + collection_cost(STW_time_in_seconds, interval_in_seconds) + 1.581 + concurrent_cost; 1.582 + 1.583 + if (PrintAdaptiveSizePolicy && Verbose) { 1.584 + gclog_or_tty->print_cr(" msc_collection_end:\n" 1.585 + "_latest_cms_collection_end_to_collection_start_secs %f\n" 1.586 + "_latest_cms_msc_end_to_msc_start_time_secs %f\n" 1.587 + "_latest_cms_initial_mark_start_to_end_time_secs %f\n" 1.588 + "_latest_cms_remark_start_to_end_time_secs %f\n" 1.589 + "latest_cms_sum_concurrent_phases_time_secs %f\n", 1.590 + _latest_cms_collection_end_to_collection_start_secs, 1.591 + _latest_cms_msc_end_to_msc_start_time_secs, 1.592 + _latest_cms_initial_mark_start_to_end_time_secs, 1.593 + _latest_cms_remark_start_to_end_time_secs, 1.594 + latest_cms_sum_concurrent_phases_time_secs); 1.595 + 1.596 + gclog_or_tty->print_cr(" msc_collection_end: \n" 1.597 + "latest_cms_sum_concurrent_phases_time_secs %f\n" 1.598 + "STW_time_in_seconds %f\n" 1.599 + "msc_pause_in_seconds %f\n", 1.600 + latest_cms_sum_concurrent_phases_time_secs, 1.601 + STW_time_in_seconds, 1.602 + msc_pause_in_seconds); 1.603 + } 1.604 + 1.605 + double cost = concurrent_cost + STW_collection_cost + 1.606 + collection_cost(msc_pause_in_seconds, interval_in_seconds); 1.607 + 1.608 + _avg_msc_gc_cost->sample(cost); 1.609 + 1.610 + // Average this ms cost into all the other types gc costs 1.611 + avg_major_gc_cost()->sample(cost); 1.612 + 1.613 + // Sample for performance counter 1.614 + _avg_msc_interval->sample(interval_in_seconds); 1.615 + if (PrintAdaptiveSizePolicy && Verbose) { 1.616 + gclog_or_tty->print("cmsAdaptiveSizePolicy::msc_collection_end: " 1.617 + "MSC gc cost: %f average: %f", cost, 1.618 + _avg_msc_gc_cost->average()); 1.619 + 1.620 + double msc_pause_in_ms = msc_pause_in_seconds * MILLIUNITS; 1.621 + gclog_or_tty->print_cr(" MSC pause: %f (ms) MSC period %f (ms)", 1.622 + msc_pause_in_ms, (double) interval_in_seconds * MILLIUNITS); 1.623 + } 1.624 + } 1.625 + } 1.626 + 1.627 + clear_internal_time_intervals(); 1.628 + 1.629 + // Can this call be put into the epilogue? 1.630 + set_first_after_collection(); 1.631 + 1.632 + // The concurrent phases keeps track of it's own mutator interval 1.633 + // with this timer. This allows the stop-the-world phase to 1.634 + // be included in the mutator time so that the stop-the-world time 1.635 + // is not double counted. Reset and start it. 1.636 + _concurrent_timer.stop(); 1.637 + _concurrent_timer.reset(); 1.638 + _concurrent_timer.start(); 1.639 + 1.640 + _STW_timer.reset(); 1.641 + _STW_timer.start(); 1.642 +} 1.643 + 1.644 +void CMSAdaptiveSizePolicy::ms_collection_begin() { 1.645 + if (PrintAdaptiveSizePolicy && Verbose) { 1.646 + gclog_or_tty->print(" "); 1.647 + gclog_or_tty->stamp(); 1.648 + gclog_or_tty->print(": ms_collection_begin "); 1.649 + } 1.650 + _STW_timer.stop(); 1.651 + _latest_cms_ms_end_to_ms_start = _STW_timer.seconds(); 1.652 + if (PrintAdaptiveSizePolicy && Verbose) { 1.653 + gclog_or_tty->print_cr("CMSAdaptiveSizePolicy::ms_collection_begin: " 1.654 + "mutator time %f", 1.655 + _latest_cms_ms_end_to_ms_start); 1.656 + } 1.657 + avg_ms_interval()->sample(_STW_timer.seconds()); 1.658 + _STW_timer.reset(); 1.659 + _STW_timer.start(); 1.660 +} 1.661 + 1.662 +void CMSAdaptiveSizePolicy::ms_collection_end(GCCause::Cause gc_cause) { 1.663 + if (PrintAdaptiveSizePolicy && Verbose) { 1.664 + gclog_or_tty->print(" "); 1.665 + gclog_or_tty->stamp(); 1.666 + gclog_or_tty->print(": ms_collection_end "); 1.667 + } 1.668 + _STW_timer.stop(); 1.669 + if (gc_cause != GCCause::_java_lang_system_gc || 1.670 + UseAdaptiveSizePolicyWithSystemGC) { 1.671 + // The MS collection is a foreground collection that does all 1.672 + // the parts of a mostly concurrent collection. 1.673 + // 1.674 + // For this collection include the cost of the 1.675 + // initial mark 1.676 + // remark 1.677 + // all concurrent time (scaled down by the 1.678 + // concurrent_processor_fraction). Some 1.679 + // may be zero if the baton was passed before 1.680 + // it was reached. 1.681 + // concurrent marking 1.682 + // sweeping 1.683 + // resetting 1.684 + // STW after baton was passed (STW_in_foreground_in_seconds) 1.685 + double STW_in_foreground_in_seconds = _STW_timer.seconds(); 1.686 + 1.687 + double latest_cms_sum_concurrent_phases_time_secs = 1.688 + concurrent_collection_time(); 1.689 + if (PrintAdaptiveSizePolicy && Verbose) { 1.690 + gclog_or_tty->print_cr("\nCMSAdaptiveSizePolicy::ms_collecton_end " 1.691 + "STW_in_foreground_in_seconds %f " 1.692 + "_latest_cms_initial_mark_start_to_end_time_secs %f " 1.693 + "_latest_cms_remark_start_to_end_time_secs %f " 1.694 + "latest_cms_sum_concurrent_phases_time_secs %f " 1.695 + "_latest_cms_ms_marking_start_to_end_time_secs %f " 1.696 + "_latest_cms_ms_end_to_ms_start %f", 1.697 + STW_in_foreground_in_seconds, 1.698 + _latest_cms_initial_mark_start_to_end_time_secs, 1.699 + _latest_cms_remark_start_to_end_time_secs, 1.700 + latest_cms_sum_concurrent_phases_time_secs, 1.701 + _latest_cms_ms_marking_start_to_end_time_secs, 1.702 + _latest_cms_ms_end_to_ms_start); 1.703 + } 1.704 + 1.705 + double STW_marking_in_seconds = _latest_cms_initial_mark_start_to_end_time_secs + 1.706 + _latest_cms_remark_start_to_end_time_secs; 1.707 +#ifndef CLOCK_GRANULARITY_TOO_LARGE 1.708 + assert(_latest_cms_ms_marking_start_to_end_time_secs == 0.0 || 1.709 + latest_cms_sum_concurrent_phases_time_secs == 0.0, 1.710 + "marking done twice?"); 1.711 +#endif 1.712 + double ms_time_in_seconds = STW_marking_in_seconds + 1.713 + STW_in_foreground_in_seconds + 1.714 + _latest_cms_ms_marking_start_to_end_time_secs + 1.715 + scaled_concurrent_collection_time(); 1.716 + avg_ms_pause()->sample(ms_time_in_seconds); 1.717 + // Use the STW costs from the initial mark and remark plus 1.718 + // the cost of the concurrent phase to calculate a 1.719 + // collection cost. 1.720 + double cost = 0.0; 1.721 + if ((_latest_cms_ms_end_to_ms_start > 0.0) && 1.722 + (ms_time_in_seconds > 0.0)) { 1.723 + double interval_in_seconds = 1.724 + _latest_cms_ms_end_to_ms_start + ms_time_in_seconds; 1.725 + 1.726 + if (PrintAdaptiveSizePolicy && Verbose) { 1.727 + gclog_or_tty->print_cr("\n ms_time_in_seconds %f " 1.728 + "latest_cms_sum_concurrent_phases_time_secs %f " 1.729 + "interval_in_seconds %f", 1.730 + ms_time_in_seconds, 1.731 + latest_cms_sum_concurrent_phases_time_secs, 1.732 + interval_in_seconds); 1.733 + } 1.734 + 1.735 + cost = collection_cost(ms_time_in_seconds, interval_in_seconds); 1.736 + 1.737 + _avg_ms_gc_cost->sample(cost); 1.738 + // Average this ms cost into all the other types gc costs 1.739 + avg_major_gc_cost()->sample(cost); 1.740 + 1.741 + // Sample for performance counter 1.742 + _avg_ms_interval->sample(interval_in_seconds); 1.743 + } 1.744 + if (PrintAdaptiveSizePolicy && Verbose) { 1.745 + gclog_or_tty->print("cmsAdaptiveSizePolicy::ms_collection_end: " 1.746 + "MS gc cost: %f average: %f", cost, _avg_ms_gc_cost->average()); 1.747 + 1.748 + double ms_time_in_ms = ms_time_in_seconds * MILLIUNITS; 1.749 + gclog_or_tty->print_cr(" MS pause: %f (ms) MS period %f (ms)", 1.750 + ms_time_in_ms, 1.751 + _latest_cms_ms_end_to_ms_start * MILLIUNITS); 1.752 + } 1.753 + } 1.754 + 1.755 + // Consider putting this code (here to end) into a 1.756 + // method for convenience. 1.757 + clear_internal_time_intervals(); 1.758 + 1.759 + set_first_after_collection(); 1.760 + 1.761 + // The concurrent phases keeps track of it's own mutator interval 1.762 + // with this timer. This allows the stop-the-world phase to 1.763 + // be included in the mutator time so that the stop-the-world time 1.764 + // is not double counted. Reset and start it. 1.765 + _concurrent_timer.stop(); 1.766 + _concurrent_timer.reset(); 1.767 + _concurrent_timer.start(); 1.768 + 1.769 + _STW_timer.reset(); 1.770 + _STW_timer.start(); 1.771 +} 1.772 + 1.773 +void CMSAdaptiveSizePolicy::clear_internal_time_intervals() { 1.774 + _latest_cms_reset_end_to_initial_mark_start_secs = 0.0; 1.775 + _latest_cms_initial_mark_end_to_remark_start_secs = 0.0; 1.776 + _latest_cms_collection_end_to_collection_start_secs = 0.0; 1.777 + _latest_cms_concurrent_marking_time_secs = 0.0; 1.778 + _latest_cms_concurrent_precleaning_time_secs = 0.0; 1.779 + _latest_cms_concurrent_sweeping_time_secs = 0.0; 1.780 + _latest_cms_msc_end_to_msc_start_time_secs = 0.0; 1.781 + _latest_cms_ms_end_to_ms_start = 0.0; 1.782 + _latest_cms_remark_start_to_end_time_secs = 0.0; 1.783 + _latest_cms_initial_mark_start_to_end_time_secs = 0.0; 1.784 + _latest_cms_ms_marking_start_to_end_time_secs = 0.0; 1.785 +} 1.786 + 1.787 +void CMSAdaptiveSizePolicy::clear_generation_free_space_flags() { 1.788 + AdaptiveSizePolicy::clear_generation_free_space_flags(); 1.789 + 1.790 + set_change_young_gen_for_maj_pauses(0); 1.791 +} 1.792 + 1.793 +void CMSAdaptiveSizePolicy::concurrent_phases_resume() { 1.794 + if (PrintAdaptiveSizePolicy && Verbose) { 1.795 + gclog_or_tty->stamp(); 1.796 + gclog_or_tty->print_cr("CMSAdaptiveSizePolicy::concurrent_phases_resume()"); 1.797 + } 1.798 + _concurrent_timer.start(); 1.799 +} 1.800 + 1.801 +double CMSAdaptiveSizePolicy::time_since_major_gc() const { 1.802 + _concurrent_timer.stop(); 1.803 + double time_since_cms_gc = _concurrent_timer.seconds(); 1.804 + _concurrent_timer.start(); 1.805 + _STW_timer.stop(); 1.806 + double time_since_STW_gc = _STW_timer.seconds(); 1.807 + _STW_timer.start(); 1.808 + 1.809 + return MIN2(time_since_cms_gc, time_since_STW_gc); 1.810 +} 1.811 + 1.812 +double CMSAdaptiveSizePolicy::major_gc_interval_average_for_decay() const { 1.813 + double cms_interval = _avg_concurrent_interval->average(); 1.814 + double msc_interval = _avg_msc_interval->average(); 1.815 + double ms_interval = _avg_ms_interval->average(); 1.816 + 1.817 + return MAX3(cms_interval, msc_interval, ms_interval); 1.818 +} 1.819 + 1.820 +double CMSAdaptiveSizePolicy::cms_gc_cost() const { 1.821 + return avg_major_gc_cost()->average(); 1.822 +} 1.823 + 1.824 +void CMSAdaptiveSizePolicy::ms_collection_marking_begin() { 1.825 + _STW_timer.stop(); 1.826 + // Start accumumlating time for the marking in the STW timer. 1.827 + _STW_timer.reset(); 1.828 + _STW_timer.start(); 1.829 +} 1.830 + 1.831 +void CMSAdaptiveSizePolicy::ms_collection_marking_end( 1.832 + GCCause::Cause gc_cause) { 1.833 + _STW_timer.stop(); 1.834 + if (gc_cause != GCCause::_java_lang_system_gc || 1.835 + UseAdaptiveSizePolicyWithSystemGC) { 1.836 + _latest_cms_ms_marking_start_to_end_time_secs = _STW_timer.seconds(); 1.837 + if (PrintAdaptiveSizePolicy && Verbose) { 1.838 + gclog_or_tty->print_cr("CMSAdaptiveSizePolicy::" 1.839 + "msc_collection_marking_end: mutator time %f", 1.840 + _latest_cms_ms_marking_start_to_end_time_secs); 1.841 + } 1.842 + } 1.843 + _STW_timer.reset(); 1.844 + _STW_timer.start(); 1.845 +} 1.846 + 1.847 +double CMSAdaptiveSizePolicy::gc_cost() const { 1.848 + double cms_gen_cost = cms_gc_cost(); 1.849 + double result = MIN2(1.0, minor_gc_cost() + cms_gen_cost); 1.850 + assert(result >= 0.0, "Both minor and major costs are non-negative"); 1.851 + return result; 1.852 +} 1.853 + 1.854 +// Cost of collection (unit-less) 1.855 +double CMSAdaptiveSizePolicy::collection_cost(double pause_in_seconds, 1.856 + double interval_in_seconds) { 1.857 + // Cost of collection (unit-less) 1.858 + double cost = 0.0; 1.859 + if ((interval_in_seconds > 0.0) && 1.860 + (pause_in_seconds > 0.0)) { 1.861 + cost = 1.862 + pause_in_seconds / interval_in_seconds; 1.863 + } 1.864 + return cost; 1.865 +} 1.866 + 1.867 +size_t CMSAdaptiveSizePolicy::adjust_eden_for_pause_time(size_t cur_eden) { 1.868 + size_t change = 0; 1.869 + size_t desired_eden = cur_eden; 1.870 + 1.871 + // reduce eden size 1.872 + change = eden_decrement_aligned_down(cur_eden); 1.873 + desired_eden = cur_eden - change; 1.874 + 1.875 + if (PrintAdaptiveSizePolicy && Verbose) { 1.876 + gclog_or_tty->print_cr( 1.877 + "CMSAdaptiveSizePolicy::adjust_eden_for_pause_time " 1.878 + "adjusting eden for pause time. " 1.879 + " starting eden size " SIZE_FORMAT 1.880 + " reduced eden size " SIZE_FORMAT 1.881 + " eden delta " SIZE_FORMAT, 1.882 + cur_eden, desired_eden, change); 1.883 + } 1.884 + 1.885 + return desired_eden; 1.886 +} 1.887 + 1.888 +size_t CMSAdaptiveSizePolicy::adjust_eden_for_throughput(size_t cur_eden) { 1.889 + 1.890 + size_t desired_eden = cur_eden; 1.891 + 1.892 + set_change_young_gen_for_throughput(increase_young_gen_for_througput_true); 1.893 + 1.894 + size_t change = eden_increment_aligned_up(cur_eden); 1.895 + size_t scaled_change = scale_by_gen_gc_cost(change, minor_gc_cost()); 1.896 + 1.897 + if (cur_eden + scaled_change > cur_eden) { 1.898 + desired_eden = cur_eden + scaled_change; 1.899 + } 1.900 + 1.901 + _young_gen_change_for_minor_throughput++; 1.902 + 1.903 + if (PrintAdaptiveSizePolicy && Verbose) { 1.904 + gclog_or_tty->print_cr( 1.905 + "CMSAdaptiveSizePolicy::adjust_eden_for_throughput " 1.906 + "adjusting eden for throughput. " 1.907 + " starting eden size " SIZE_FORMAT 1.908 + " increased eden size " SIZE_FORMAT 1.909 + " eden delta " SIZE_FORMAT, 1.910 + cur_eden, desired_eden, scaled_change); 1.911 + } 1.912 + 1.913 + return desired_eden; 1.914 +} 1.915 + 1.916 +size_t CMSAdaptiveSizePolicy::adjust_eden_for_footprint(size_t cur_eden) { 1.917 + 1.918 + set_decrease_for_footprint(decrease_young_gen_for_footprint_true); 1.919 + 1.920 + size_t change = eden_decrement(cur_eden); 1.921 + size_t desired_eden_size = cur_eden - change; 1.922 + 1.923 + if (PrintAdaptiveSizePolicy && Verbose) { 1.924 + gclog_or_tty->print_cr( 1.925 + "CMSAdaptiveSizePolicy::adjust_eden_for_footprint " 1.926 + "adjusting eden for footprint. " 1.927 + " starting eden size " SIZE_FORMAT 1.928 + " reduced eden size " SIZE_FORMAT 1.929 + " eden delta " SIZE_FORMAT, 1.930 + cur_eden, desired_eden_size, change); 1.931 + } 1.932 + return desired_eden_size; 1.933 +} 1.934 + 1.935 +// The eden and promo versions should be combined if possible. 1.936 +// They are the same except that the sizes of the decrement 1.937 +// and increment are different for eden and promo. 1.938 +size_t CMSAdaptiveSizePolicy::eden_decrement_aligned_down(size_t cur_eden) { 1.939 + size_t delta = eden_decrement(cur_eden); 1.940 + return align_size_down(delta, generation_alignment()); 1.941 +} 1.942 + 1.943 +size_t CMSAdaptiveSizePolicy::eden_increment_aligned_up(size_t cur_eden) { 1.944 + size_t delta = eden_increment(cur_eden); 1.945 + return align_size_up(delta, generation_alignment()); 1.946 +} 1.947 + 1.948 +size_t CMSAdaptiveSizePolicy::promo_decrement_aligned_down(size_t cur_promo) { 1.949 + size_t delta = promo_decrement(cur_promo); 1.950 + return align_size_down(delta, generation_alignment()); 1.951 +} 1.952 + 1.953 +size_t CMSAdaptiveSizePolicy::promo_increment_aligned_up(size_t cur_promo) { 1.954 + size_t delta = promo_increment(cur_promo); 1.955 + return align_size_up(delta, generation_alignment()); 1.956 +} 1.957 + 1.958 + 1.959 +void CMSAdaptiveSizePolicy::compute_young_generation_free_space(size_t cur_eden, 1.960 + size_t max_eden_size) 1.961 +{ 1.962 + size_t desired_eden_size = cur_eden; 1.963 + size_t eden_limit = max_eden_size; 1.964 + 1.965 + // Printout input 1.966 + if (PrintGC && PrintAdaptiveSizePolicy) { 1.967 + gclog_or_tty->print_cr( 1.968 + "CMSAdaptiveSizePolicy::compute_young_generation_free_space: " 1.969 + "cur_eden " SIZE_FORMAT, 1.970 + cur_eden); 1.971 + } 1.972 + 1.973 + // Used for diagnostics 1.974 + clear_generation_free_space_flags(); 1.975 + 1.976 + if (_avg_minor_pause->padded_average() > gc_pause_goal_sec()) { 1.977 + if (minor_pause_young_estimator()->decrement_will_decrease()) { 1.978 + // If the minor pause is too long, shrink the young gen. 1.979 + set_change_young_gen_for_min_pauses( 1.980 + decrease_young_gen_for_min_pauses_true); 1.981 + desired_eden_size = adjust_eden_for_pause_time(desired_eden_size); 1.982 + } 1.983 + } else if ((avg_remark_pause()->padded_average() > gc_pause_goal_sec()) || 1.984 + (avg_initial_pause()->padded_average() > gc_pause_goal_sec())) { 1.985 + // The remark or initial pauses are not meeting the goal. Should 1.986 + // the generation be shrunk? 1.987 + if (get_and_clear_first_after_collection() && 1.988 + ((avg_remark_pause()->padded_average() > gc_pause_goal_sec() && 1.989 + remark_pause_young_estimator()->decrement_will_decrease()) || 1.990 + (avg_initial_pause()->padded_average() > gc_pause_goal_sec() && 1.991 + initial_pause_young_estimator()->decrement_will_decrease()))) { 1.992 + 1.993 + set_change_young_gen_for_maj_pauses( 1.994 + decrease_young_gen_for_maj_pauses_true); 1.995 + 1.996 + // If the remark or initial pause is too long and this is the 1.997 + // first young gen collection after a cms collection, shrink 1.998 + // the young gen. 1.999 + desired_eden_size = adjust_eden_for_pause_time(desired_eden_size); 1.1000 + } 1.1001 + // If not the first young gen collection after a cms collection, 1.1002 + // don't do anything. In this case an adjustment has already 1.1003 + // been made and the results of the adjustment has not yet been 1.1004 + // measured. 1.1005 + } else if ((minor_gc_cost() >= 0.0) && 1.1006 + (adjusted_mutator_cost() < _throughput_goal)) { 1.1007 + desired_eden_size = adjust_eden_for_throughput(desired_eden_size); 1.1008 + } else { 1.1009 + desired_eden_size = adjust_eden_for_footprint(desired_eden_size); 1.1010 + } 1.1011 + 1.1012 + if (PrintGC && PrintAdaptiveSizePolicy) { 1.1013 + gclog_or_tty->print_cr( 1.1014 + "CMSAdaptiveSizePolicy::compute_young_generation_free_space limits:" 1.1015 + " desired_eden_size: " SIZE_FORMAT 1.1016 + " old_eden_size: " SIZE_FORMAT, 1.1017 + desired_eden_size, cur_eden); 1.1018 + } 1.1019 + 1.1020 + set_eden_size(desired_eden_size); 1.1021 +} 1.1022 + 1.1023 +size_t CMSAdaptiveSizePolicy::adjust_promo_for_pause_time(size_t cur_promo) { 1.1024 + size_t change = 0; 1.1025 + size_t desired_promo = cur_promo; 1.1026 + // Move this test up to caller like the adjust_eden_for_pause_time() 1.1027 + // call. 1.1028 + if ((AdaptiveSizePausePolicy == 0) && 1.1029 + ((avg_remark_pause()->padded_average() > gc_pause_goal_sec()) || 1.1030 + (avg_initial_pause()->padded_average() > gc_pause_goal_sec()))) { 1.1031 + set_change_old_gen_for_maj_pauses(decrease_old_gen_for_maj_pauses_true); 1.1032 + change = promo_decrement_aligned_down(cur_promo); 1.1033 + desired_promo = cur_promo - change; 1.1034 + } else if ((AdaptiveSizePausePolicy > 0) && 1.1035 + (((avg_remark_pause()->padded_average() > gc_pause_goal_sec()) && 1.1036 + remark_pause_old_estimator()->decrement_will_decrease()) || 1.1037 + ((avg_initial_pause()->padded_average() > gc_pause_goal_sec()) && 1.1038 + initial_pause_old_estimator()->decrement_will_decrease()))) { 1.1039 + set_change_old_gen_for_maj_pauses(decrease_old_gen_for_maj_pauses_true); 1.1040 + change = promo_decrement_aligned_down(cur_promo); 1.1041 + desired_promo = cur_promo - change; 1.1042 + } 1.1043 + 1.1044 + if ((change != 0) &&PrintAdaptiveSizePolicy && Verbose) { 1.1045 + gclog_or_tty->print_cr( 1.1046 + "CMSAdaptiveSizePolicy::adjust_promo_for_pause_time " 1.1047 + "adjusting promo for pause time. " 1.1048 + " starting promo size " SIZE_FORMAT 1.1049 + " reduced promo size " SIZE_FORMAT 1.1050 + " promo delta " SIZE_FORMAT, 1.1051 + cur_promo, desired_promo, change); 1.1052 + } 1.1053 + 1.1054 + return desired_promo; 1.1055 +} 1.1056 + 1.1057 +// Try to share this with PS. 1.1058 +size_t CMSAdaptiveSizePolicy::scale_by_gen_gc_cost(size_t base_change, 1.1059 + double gen_gc_cost) { 1.1060 + 1.1061 + // Calculate the change to use for the tenured gen. 1.1062 + size_t scaled_change = 0; 1.1063 + // Can the increment to the generation be scaled? 1.1064 + if (gc_cost() >= 0.0 && gen_gc_cost >= 0.0) { 1.1065 + double scale_by_ratio = gen_gc_cost / gc_cost(); 1.1066 + scaled_change = 1.1067 + (size_t) (scale_by_ratio * (double) base_change); 1.1068 + if (PrintAdaptiveSizePolicy && Verbose) { 1.1069 + gclog_or_tty->print_cr( 1.1070 + "Scaled tenured increment: " SIZE_FORMAT " by %f down to " 1.1071 + SIZE_FORMAT, 1.1072 + base_change, scale_by_ratio, scaled_change); 1.1073 + } 1.1074 + } else if (gen_gc_cost >= 0.0) { 1.1075 + // Scaling is not going to work. If the major gc time is the 1.1076 + // larger than the other GC costs, give it a full increment. 1.1077 + if (gen_gc_cost >= (gc_cost() - gen_gc_cost)) { 1.1078 + scaled_change = base_change; 1.1079 + } 1.1080 + } else { 1.1081 + // Don't expect to get here but it's ok if it does 1.1082 + // in the product build since the delta will be 0 1.1083 + // and nothing will change. 1.1084 + assert(false, "Unexpected value for gc costs"); 1.1085 + } 1.1086 + 1.1087 + return scaled_change; 1.1088 +} 1.1089 + 1.1090 +size_t CMSAdaptiveSizePolicy::adjust_promo_for_throughput(size_t cur_promo) { 1.1091 + 1.1092 + size_t desired_promo = cur_promo; 1.1093 + 1.1094 + set_change_old_gen_for_throughput(increase_old_gen_for_throughput_true); 1.1095 + 1.1096 + size_t change = promo_increment_aligned_up(cur_promo); 1.1097 + size_t scaled_change = scale_by_gen_gc_cost(change, major_gc_cost()); 1.1098 + 1.1099 + if (cur_promo + scaled_change > cur_promo) { 1.1100 + desired_promo = cur_promo + scaled_change; 1.1101 + } 1.1102 + 1.1103 + _old_gen_change_for_major_throughput++; 1.1104 + 1.1105 + if (PrintAdaptiveSizePolicy && Verbose) { 1.1106 + gclog_or_tty->print_cr( 1.1107 + "CMSAdaptiveSizePolicy::adjust_promo_for_throughput " 1.1108 + "adjusting promo for throughput. " 1.1109 + " starting promo size " SIZE_FORMAT 1.1110 + " increased promo size " SIZE_FORMAT 1.1111 + " promo delta " SIZE_FORMAT, 1.1112 + cur_promo, desired_promo, scaled_change); 1.1113 + } 1.1114 + 1.1115 + return desired_promo; 1.1116 +} 1.1117 + 1.1118 +size_t CMSAdaptiveSizePolicy::adjust_promo_for_footprint(size_t cur_promo, 1.1119 + size_t cur_eden) { 1.1120 + 1.1121 + set_decrease_for_footprint(decrease_young_gen_for_footprint_true); 1.1122 + 1.1123 + size_t change = promo_decrement(cur_promo); 1.1124 + size_t desired_promo_size = cur_promo - change; 1.1125 + 1.1126 + if (PrintAdaptiveSizePolicy && Verbose) { 1.1127 + gclog_or_tty->print_cr( 1.1128 + "CMSAdaptiveSizePolicy::adjust_promo_for_footprint " 1.1129 + "adjusting promo for footprint. " 1.1130 + " starting promo size " SIZE_FORMAT 1.1131 + " reduced promo size " SIZE_FORMAT 1.1132 + " promo delta " SIZE_FORMAT, 1.1133 + cur_promo, desired_promo_size, change); 1.1134 + } 1.1135 + return desired_promo_size; 1.1136 +} 1.1137 + 1.1138 +void CMSAdaptiveSizePolicy::compute_tenured_generation_free_space( 1.1139 + size_t cur_tenured_free, 1.1140 + size_t max_tenured_available, 1.1141 + size_t cur_eden) { 1.1142 + // This can be bad if the desired value grows/shrinks without 1.1143 + // any connection to the read free space 1.1144 + size_t desired_promo_size = promo_size(); 1.1145 + size_t tenured_limit = max_tenured_available; 1.1146 + 1.1147 + // Printout input 1.1148 + if (PrintGC && PrintAdaptiveSizePolicy) { 1.1149 + gclog_or_tty->print_cr( 1.1150 + "CMSAdaptiveSizePolicy::compute_tenured_generation_free_space: " 1.1151 + "cur_tenured_free " SIZE_FORMAT 1.1152 + " max_tenured_available " SIZE_FORMAT, 1.1153 + cur_tenured_free, max_tenured_available); 1.1154 + } 1.1155 + 1.1156 + // Used for diagnostics 1.1157 + clear_generation_free_space_flags(); 1.1158 + 1.1159 + set_decide_at_full_gc(decide_at_full_gc_true); 1.1160 + if (avg_remark_pause()->padded_average() > gc_pause_goal_sec() || 1.1161 + avg_initial_pause()->padded_average() > gc_pause_goal_sec()) { 1.1162 + desired_promo_size = adjust_promo_for_pause_time(cur_tenured_free); 1.1163 + } else if (avg_minor_pause()->padded_average() > gc_pause_goal_sec()) { 1.1164 + // Nothing to do since the minor collections are too large and 1.1165 + // this method only deals with the cms generation. 1.1166 + } else if ((cms_gc_cost() >= 0.0) && 1.1167 + (adjusted_mutator_cost() < _throughput_goal)) { 1.1168 + desired_promo_size = adjust_promo_for_throughput(cur_tenured_free); 1.1169 + } else { 1.1170 + desired_promo_size = adjust_promo_for_footprint(cur_tenured_free, 1.1171 + cur_eden); 1.1172 + } 1.1173 + 1.1174 + if (PrintGC && PrintAdaptiveSizePolicy) { 1.1175 + gclog_or_tty->print_cr( 1.1176 + "CMSAdaptiveSizePolicy::compute_tenured_generation_free_space limits:" 1.1177 + " desired_promo_size: " SIZE_FORMAT 1.1178 + " old_promo_size: " SIZE_FORMAT, 1.1179 + desired_promo_size, cur_tenured_free); 1.1180 + } 1.1181 + 1.1182 + set_promo_size(desired_promo_size); 1.1183 +} 1.1184 + 1.1185 +int CMSAdaptiveSizePolicy::compute_survivor_space_size_and_threshold( 1.1186 + bool is_survivor_overflow, 1.1187 + int tenuring_threshold, 1.1188 + size_t survivor_limit) { 1.1189 + assert(survivor_limit >= generation_alignment(), 1.1190 + "survivor_limit too small"); 1.1191 + assert((size_t)align_size_down(survivor_limit, generation_alignment()) 1.1192 + == survivor_limit, "survivor_limit not aligned"); 1.1193 + 1.1194 + // Change UsePSAdaptiveSurvivorSizePolicy -> UseAdaptiveSurvivorSizePolicy? 1.1195 + if (!UsePSAdaptiveSurvivorSizePolicy || 1.1196 + !young_gen_policy_is_ready()) { 1.1197 + return tenuring_threshold; 1.1198 + } 1.1199 + 1.1200 + // We'll decide whether to increase or decrease the tenuring 1.1201 + // threshold based partly on the newly computed survivor size 1.1202 + // (if we hit the maximum limit allowed, we'll always choose to 1.1203 + // decrement the threshold). 1.1204 + bool incr_tenuring_threshold = false; 1.1205 + bool decr_tenuring_threshold = false; 1.1206 + 1.1207 + set_decrement_tenuring_threshold_for_gc_cost(false); 1.1208 + set_increment_tenuring_threshold_for_gc_cost(false); 1.1209 + set_decrement_tenuring_threshold_for_survivor_limit(false); 1.1210 + 1.1211 + if (!is_survivor_overflow) { 1.1212 + // Keep running averages on how much survived 1.1213 + 1.1214 + // We use the tenuring threshold to equalize the cost of major 1.1215 + // and minor collections. 1.1216 + // ThresholdTolerance is used to indicate how sensitive the 1.1217 + // tenuring threshold is to differences in cost betweent the 1.1218 + // collection types. 1.1219 + 1.1220 + // Get the times of interest. This involves a little work, so 1.1221 + // we cache the values here. 1.1222 + const double major_cost = major_gc_cost(); 1.1223 + const double minor_cost = minor_gc_cost(); 1.1224 + 1.1225 + if (minor_cost > major_cost * _threshold_tolerance_percent) { 1.1226 + // Minor times are getting too long; lower the threshold so 1.1227 + // less survives and more is promoted. 1.1228 + decr_tenuring_threshold = true; 1.1229 + set_decrement_tenuring_threshold_for_gc_cost(true); 1.1230 + } else if (major_cost > minor_cost * _threshold_tolerance_percent) { 1.1231 + // Major times are too long, so we want less promotion. 1.1232 + incr_tenuring_threshold = true; 1.1233 + set_increment_tenuring_threshold_for_gc_cost(true); 1.1234 + } 1.1235 + 1.1236 + } else { 1.1237 + // Survivor space overflow occurred, so promoted and survived are 1.1238 + // not accurate. We'll make our best guess by combining survived 1.1239 + // and promoted and count them as survivors. 1.1240 + // 1.1241 + // We'll lower the tenuring threshold to see if we can correct 1.1242 + // things. Also, set the survivor size conservatively. We're 1.1243 + // trying to avoid many overflows from occurring if defnew size 1.1244 + // is just too small. 1.1245 + 1.1246 + decr_tenuring_threshold = true; 1.1247 + } 1.1248 + 1.1249 + // The padded average also maintains a deviation from the average; 1.1250 + // we use this to see how good of an estimate we have of what survived. 1.1251 + // We're trying to pad the survivor size as little as possible without 1.1252 + // overflowing the survivor spaces. 1.1253 + size_t target_size = align_size_up((size_t)_avg_survived->padded_average(), 1.1254 + generation_alignment()); 1.1255 + target_size = MAX2(target_size, generation_alignment()); 1.1256 + 1.1257 + if (target_size > survivor_limit) { 1.1258 + // Target size is bigger than we can handle. Let's also reduce 1.1259 + // the tenuring threshold. 1.1260 + target_size = survivor_limit; 1.1261 + decr_tenuring_threshold = true; 1.1262 + set_decrement_tenuring_threshold_for_survivor_limit(true); 1.1263 + } 1.1264 + 1.1265 + // Finally, increment or decrement the tenuring threshold, as decided above. 1.1266 + // We test for decrementing first, as we might have hit the target size 1.1267 + // limit. 1.1268 + if (decr_tenuring_threshold && !(AlwaysTenure || NeverTenure)) { 1.1269 + if (tenuring_threshold > 1) { 1.1270 + tenuring_threshold--; 1.1271 + } 1.1272 + } else if (incr_tenuring_threshold && !(AlwaysTenure || NeverTenure)) { 1.1273 + if (tenuring_threshold < MaxTenuringThreshold) { 1.1274 + tenuring_threshold++; 1.1275 + } 1.1276 + } 1.1277 + 1.1278 + // We keep a running average of the amount promoted which is used 1.1279 + // to decide when we should collect the old generation (when 1.1280 + // the amount of old gen free space is less than what we expect to 1.1281 + // promote). 1.1282 + 1.1283 + if (PrintAdaptiveSizePolicy) { 1.1284 + // A little more detail if Verbose is on 1.1285 + GenCollectedHeap* gch = GenCollectedHeap::heap(); 1.1286 + if (Verbose) { 1.1287 + gclog_or_tty->print( " avg_survived: %f" 1.1288 + " avg_deviation: %f", 1.1289 + _avg_survived->average(), 1.1290 + _avg_survived->deviation()); 1.1291 + } 1.1292 + 1.1293 + gclog_or_tty->print( " avg_survived_padded_avg: %f", 1.1294 + _avg_survived->padded_average()); 1.1295 + 1.1296 + if (Verbose) { 1.1297 + gclog_or_tty->print( " avg_promoted_avg: %f" 1.1298 + " avg_promoted_dev: %f", 1.1299 + gch->gc_stats(1)->avg_promoted()->average(), 1.1300 + gch->gc_stats(1)->avg_promoted()->deviation()); 1.1301 + } 1.1302 + 1.1303 + gclog_or_tty->print( " avg_promoted_padded_avg: %f" 1.1304 + " avg_pretenured_padded_avg: %f" 1.1305 + " tenuring_thresh: %d" 1.1306 + " target_size: " SIZE_FORMAT 1.1307 + " survivor_limit: " SIZE_FORMAT, 1.1308 + gch->gc_stats(1)->avg_promoted()->padded_average(), 1.1309 + _avg_pretenured->padded_average(), 1.1310 + tenuring_threshold, target_size, survivor_limit); 1.1311 + gclog_or_tty->cr(); 1.1312 + } 1.1313 + 1.1314 + set_survivor_size(target_size); 1.1315 + 1.1316 + return tenuring_threshold; 1.1317 +} 1.1318 + 1.1319 +bool CMSAdaptiveSizePolicy::get_and_clear_first_after_collection() { 1.1320 + bool result = _first_after_collection; 1.1321 + _first_after_collection = false; 1.1322 + return result; 1.1323 +} 1.1324 + 1.1325 +bool CMSAdaptiveSizePolicy::print_adaptive_size_policy_on( 1.1326 + outputStream* st) const { 1.1327 + 1.1328 + if (!UseAdaptiveSizePolicy) return false; 1.1329 + 1.1330 + GenCollectedHeap* gch = GenCollectedHeap::heap(); 1.1331 + Generation* gen0 = gch->get_gen(0); 1.1332 + DefNewGeneration* def_new = gen0->as_DefNewGeneration(); 1.1333 + return 1.1334 + AdaptiveSizePolicy::print_adaptive_size_policy_on( 1.1335 + st, 1.1336 + def_new->tenuring_threshold()); 1.1337 +}