1 /* 2 * Copyright (c) 2013, 2015, Red Hat, Inc. and/or its affiliates. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 * 22 */ 23 24 #include "gc/shared/gcPolicyCounters.hpp" 25 #include "gc/shenandoah/shenandoahCollectionSet.hpp" 26 #include "gc/shenandoah/shenandoahFreeSet.hpp" 27 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" 28 #include "gc/shenandoah/shenandoahHeap.inline.hpp" 29 #include "gc/shenandoah/shenandoahPhaseTimes.hpp" 30 31 int compareHeapRegionsByGarbage(ShenandoahHeapRegion* a, ShenandoahHeapRegion* b) { 32 if (a == NULL) { 33 if (b == NULL) { 34 return 0; 35 } else { 36 return 1; 37 } 38 } else if (b == NULL) { 39 return -1; 40 } 41 42 size_t garbage_a = a->garbage(); 43 size_t garbage_b = b->garbage(); 44 45 if (garbage_a > garbage_b) 46 return -1; 47 else if (garbage_a < garbage_b) 48 return 1; 49 else return 0; 50 } 51 52 class ShenandoahHeuristics : public CHeapObj<mtGC> { 53 54 NumberSeq _allocation_rate_bytes; 55 NumberSeq _reclamation_rate_bytes; 56 57 size_t _bytes_allocated_since_CM; 58 size_t _bytes_reclaimed_this_cycle; 59 60 protected: 61 size_t _bytes_allocated_start_CM; 62 size_t _bytes_allocated_during_CM; 63 64 private: 65 size_t _garbage_threshold; 66 67 public: 68 69 ShenandoahHeuristics(); 70 71 void record_bytes_allocated(size_t bytes); 72 void record_bytes_reclaimed(size_t bytes); 73 void record_bytes_start_CM(size_t bytes); 74 void record_bytes_end_CM(size_t bytes); 75 76 virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const=0; 77 78 virtual void choose_collection_set(ShenandoahCollectionSet* collection_set); 79 virtual void choose_collection_set_min_garbage(ShenandoahCollectionSet* collection_set, size_t min_garbage); 80 virtual void choose_free_set(ShenandoahFreeSet* free_set); 81 82 virtual bool process_references() { 83 if (ShenandoahRefProcFrequency == 0) return false; 84 size_t cycle = ShenandoahHeap::heap()->shenandoahPolicy()->cycle_counter(); 85 // Process references every Nth GC cycle. 86 return cycle % ShenandoahRefProcFrequency == 0; 87 } 88 89 virtual bool unload_classes() { 90 if (ShenandoahUnloadClassesFrequency == 0) return false; 91 size_t cycle = ShenandoahHeap::heap()->shenandoahPolicy()->cycle_counter(); 92 // Process references every Nth GC cycle. 93 return cycle % ShenandoahUnloadClassesFrequency == 0; 94 } 95 96 protected: 97 98 void set_garbage_threshold(size_t threshold) { 99 _garbage_threshold = threshold; 100 } 101 102 size_t garbage_threshold() { 103 return _garbage_threshold; 104 } 105 }; 106 107 ShenandoahHeuristics::ShenandoahHeuristics() : 108 _bytes_allocated_since_CM(0), 109 _bytes_reclaimed_this_cycle(0), 110 _bytes_allocated_start_CM(0), 111 _bytes_allocated_during_CM(0), 112 _garbage_threshold(ShenandoahHeapRegion::RegionSizeBytes / 2) 113 { 114 } 115 116 void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collection_set) { 117 ShenandoahHeapRegionSet* sorted_regions = ShenandoahHeap::heap()->sorted_regions(); 118 sorted_regions->sort(compareHeapRegionsByGarbage); 119 120 size_t i = 0; 121 size_t end = sorted_regions->active_regions(); 122 123 while (i < end) { 124 ShenandoahHeapRegion* region = sorted_regions->get(i++); 125 if (region->garbage() > _garbage_threshold && ! region->is_humongous() && ! region->is_pinned()) { 126 log_develop_trace(gc)("Choose region " SIZE_FORMAT " with garbage = " SIZE_FORMAT " and live = " SIZE_FORMAT " and _garbage_threshold = " SIZE_FORMAT "\n", 127 region->region_number(), region->garbage(), region->get_live_data(), _garbage_threshold); 128 129 assert(! region->is_humongous(), "no humongous regions in collection set"); 130 131 if (region->get_live_data() == 0) { 132 // We can recycle it right away and put it in the free set. 133 ShenandoahHeap::heap()->decrease_used(region->used()); 134 region->recycle(); 135 } else { 136 collection_set->add_region(region); 137 region->set_is_in_collection_set(true); 138 } 139 } else { 140 log_develop_trace(gc)("Rejected region " SIZE_FORMAT " with garbage = " SIZE_FORMAT " and live = " SIZE_FORMAT " and _garbage_threshold = " SIZE_FORMAT "\n", 141 region->region_number(), region->garbage(), region->get_live_data(), _garbage_threshold); 142 } 143 } 144 145 } 146 147 void ShenandoahHeuristics::choose_collection_set_min_garbage(ShenandoahCollectionSet* collection_set, size_t min_garbage) { 148 ShenandoahHeapRegionSet* sorted_regions = ShenandoahHeap::heap()->sorted_regions(); 149 sorted_regions->sort(compareHeapRegionsByGarbage); 150 size_t i = 0; 151 size_t end = sorted_regions->active_regions(); 152 153 size_t garbage = 0; 154 while (i < end && garbage < min_garbage) { 155 ShenandoahHeapRegion* region = sorted_regions->get(i++); 156 if (region->garbage() > _garbage_threshold && ! region->is_humongous() && ! region->is_pinned()) { 157 collection_set->add_region(region); 158 garbage += region->garbage(); 159 region->set_is_in_collection_set(true); 160 } 161 } 162 } 163 164 void ShenandoahHeuristics::choose_free_set(ShenandoahFreeSet* free_set) { 165 166 ShenandoahHeapRegionSet* ordered_regions = ShenandoahHeap::heap()->regions(); 167 size_t i = 0; 168 size_t end = ordered_regions->active_regions(); 169 170 while (i < end) { 171 ShenandoahHeapRegion* region = ordered_regions->get(i++); 172 if ((! region->is_in_collection_set()) 173 && (! region->is_humongous()) 174 && (! region->is_pinned())) { 175 free_set->add_region(region); 176 } 177 } 178 } 179 180 void ShenandoahCollectorPolicy::record_workers_start(TimingPhase phase) { 181 for (uint i = 0; i < ShenandoahPhaseTimes::GCParPhasesSentinel; i++) { 182 _phase_times->reset(i); 183 } 184 } 185 186 void ShenandoahCollectorPolicy::record_workers_end(TimingPhase phase) { 187 if (phase != _num_phases) { 188 for (uint i = 0; i < ShenandoahPhaseTimes::GCParPhasesSentinel; i++) { 189 double t = _phase_times->average(i); 190 _timing_data[phase + i]._ms.add(t * 1000.0); 191 } 192 } 193 } 194 195 void ShenandoahCollectorPolicy::record_phase_start(TimingPhase phase) { 196 _timing_data[phase]._start = os::elapsedTime(); 197 198 } 199 200 void ShenandoahCollectorPolicy::record_phase_end(TimingPhase phase) { 201 double end = os::elapsedTime(); 202 double elapsed = end - _timing_data[phase]._start; 203 _timing_data[phase]._ms.add(elapsed * 1000); 204 205 } 206 207 void ShenandoahCollectorPolicy::report_concgc_cancelled() { 208 } 209 210 void ShenandoahHeuristics::record_bytes_allocated(size_t bytes) { 211 _bytes_allocated_since_CM = bytes; 212 _bytes_allocated_start_CM = bytes; 213 _allocation_rate_bytes.add(bytes); 214 } 215 216 void ShenandoahHeuristics::record_bytes_reclaimed(size_t bytes) { 217 _bytes_reclaimed_this_cycle = bytes; 218 _reclamation_rate_bytes.add(bytes); 219 } 220 221 void ShenandoahHeuristics::record_bytes_start_CM(size_t bytes) { 222 _bytes_allocated_start_CM = bytes; 223 } 224 225 void ShenandoahHeuristics::record_bytes_end_CM(size_t bytes) { 226 _bytes_allocated_during_CM = (bytes > _bytes_allocated_start_CM) ? (bytes - _bytes_allocated_start_CM) 227 : bytes; 228 } 229 230 class PassiveHeuristics : public ShenandoahHeuristics { 231 public: 232 PassiveHeuristics() : ShenandoahHeuristics() { 233 set_garbage_threshold(8); 234 } 235 236 virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const { 237 // Never do concurrent GCs. 238 return false; 239 } 240 241 virtual bool process_references() { 242 // Randomly process refs with 50% chance. 243 return (os::random() & 1) == 1; 244 } 245 246 virtual bool unload_classes() { 247 // Randomly unload classes with 50% chance. 248 return (os::random() & 1) == 1; 249 } 250 }; 251 252 class AggressiveHeuristics : public ShenandoahHeuristics { 253 public: 254 AggressiveHeuristics() : ShenandoahHeuristics() { 255 set_garbage_threshold(8); 256 } 257 258 virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const { 259 return true; 260 } 261 262 virtual bool process_references() { 263 // Randomly process refs with 50% chance. 264 return (os::random() & 1) == 1; 265 } 266 267 virtual bool unload_classes() { 268 // Randomly unload classes with 50% chance. 269 return (os::random() & 1) == 1; 270 } 271 }; 272 273 class DynamicHeuristics : public ShenandoahHeuristics { 274 public: 275 DynamicHeuristics() : ShenandoahHeuristics() { 276 log_info(gc, init)("Shenandoah dynamic heuristics thresholds: allocation "SIZE_FORMAT", free "SIZE_FORMAT", garbage "SIZE_FORMAT, 277 ShenandoahAllocationThreshold, 278 ShenandoahFreeThreshold, 279 ShenandoahGarbageThreshold); 280 } 281 282 virtual ~DynamicHeuristics() {} 283 284 virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const { 285 286 bool shouldStartConcurrentMark = false; 287 288 ShenandoahHeap* heap = ShenandoahHeap::heap(); 289 size_t free_capacity = heap->free_regions()->capacity(); 290 size_t free_used = heap->free_regions()->used(); 291 assert(free_used <= free_capacity, "must use less than capacity"); 292 size_t available = free_capacity - free_used; 293 uintx factor = heap->need_update_refs() ? ShenandoahFreeThreshold : ShenandoahInitialFreeThreshold; 294 size_t targetStartMarking = (capacity * factor) / 100; 295 296 size_t threshold_bytes_allocated = heap->capacity() * ShenandoahAllocationThreshold / 100; 297 if (available < targetStartMarking && 298 heap->bytes_allocated_since_cm() > threshold_bytes_allocated) 299 { 300 // Need to check that an appropriate number of regions have 301 // been allocated since last concurrent mark too. 302 shouldStartConcurrentMark = true; 303 } 304 305 return shouldStartConcurrentMark; 306 } 307 308 virtual void choose_collection_set(ShenandoahCollectionSet* collection_set) { 309 set_garbage_threshold(ShenandoahHeapRegion::RegionSizeBytes * ShenandoahGarbageThreshold / 100); 310 ShenandoahHeuristics::choose_collection_set(collection_set); 311 } 312 }; 313 314 315 class AdaptiveHeuristics : public ShenandoahHeuristics { 316 private: 317 size_t _max_live_data; 318 double _used_threshold_factor; 319 double _garbage_threshold_factor; 320 double _allocation_threshold_factor; 321 322 uintx _used_threshold; 323 uintx _garbage_threshold; 324 uintx _allocation_threshold; 325 326 public: 327 AdaptiveHeuristics() : ShenandoahHeuristics() { 328 _max_live_data = 0; 329 330 _used_threshold = 0; 331 _garbage_threshold = 0; 332 _allocation_threshold = 0; 333 334 _used_threshold_factor = 0.; 335 _garbage_threshold_factor = 0.1; 336 _allocation_threshold_factor = 0.; 337 } 338 339 virtual ~AdaptiveHeuristics() {} 340 341 virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const { 342 343 ShenandoahHeap* _heap = ShenandoahHeap::heap(); 344 bool shouldStartConcurrentMark = false; 345 OrderAccess::release(); 346 347 size_t max_live_data = _max_live_data; 348 if (max_live_data == 0) { 349 max_live_data = capacity * 0.2; // Very generous initial value. 350 } else { 351 max_live_data *= 1.3; // Add some wiggle room. 352 } 353 size_t max_cycle_allocated = _heap->max_allocated_gc(); 354 if (max_cycle_allocated == 0) { 355 max_cycle_allocated = capacity * 0.3; // Very generous. 356 } else { 357 max_cycle_allocated *= 1.3; // Add 20% wiggle room. Should be enough. 358 } 359 size_t threshold = _heap->capacity() - max_cycle_allocated - max_live_data; 360 if (used > threshold) 361 { 362 shouldStartConcurrentMark = true; 363 } 364 365 return shouldStartConcurrentMark; 366 } 367 368 virtual void choose_collection_set(ShenandoahCollectionSet* collection_set) { 369 size_t bytes_alloc = ShenandoahHeap::heap()->bytes_allocated_since_cm(); 370 size_t min_garbage = bytes_alloc/* * 1.1*/; 371 set_garbage_threshold(ShenandoahHeapRegion::RegionSizeBytes * ShenandoahGarbageThreshold / 100); 372 ShenandoahHeuristics::choose_collection_set_min_garbage(collection_set, min_garbage); 373 374 log_develop_trace(gc)("Garbage to be collected: "SIZE_FORMAT, collection_set->garbage()); 375 log_develop_trace(gc)("Objects to be evacuated: "SIZE_FORMAT, collection_set->live_data()); 376 377 _max_live_data = MAX2(_max_live_data, collection_set->live_data()); 378 } 379 }; 380 381 ShenandoahCollectorPolicy::ShenandoahCollectorPolicy() : _cycle_counter(0) { 382 383 ShenandoahHeapRegion::setup_heap_region_size(initial_heap_byte_size(), max_heap_byte_size()); 384 385 initialize_all(); 386 387 _tracer = new (ResourceObj::C_HEAP, mtGC) ShenandoahTracer(); 388 _stw_timer = new (ResourceObj::C_HEAP, mtGC) STWGCTimer(); 389 _conc_timer = new (ResourceObj::C_HEAP, mtGC) ConcurrentGCTimer(); 390 _user_requested_gcs = 0; 391 _allocation_failure_gcs = 0; 392 _conc_gc_aborted = false; 393 394 _phase_names[init_mark] = "Initial Mark Pauses (net)"; 395 _phase_names[init_mark_gross] = "Initial Mark Pauses (gross)"; 396 _phase_names[final_mark] = "Final Mark Pauses (net)"; 397 _phase_names[final_mark_gross] = "Final Mark Pauses (gross)"; 398 _phase_names[accumulate_stats] = " Accumulate Stats"; 399 _phase_names[make_parsable] = " Make Parsable"; 400 _phase_names[clear_liveness] = " Clear Liveness"; 401 _phase_names[scan_roots] = " Scan Roots"; 402 _phase_names[update_roots] = " Update Roots"; 403 _phase_names[drain_satb] = " Drain SATB"; 404 _phase_names[weakrefs] = " Weak References"; 405 _phase_names[class_unloading] = " Class Unloading"; 406 _phase_names[prepare_evac] = " Prepare Evacuation"; 407 _phase_names[init_evac] = " Initial Evacuation"; 408 409 _phase_names[scan_thread_roots] = " Scan Thread Roots"; 410 _phase_names[scan_code_roots] = " Scan Code Cache Roots"; 411 _phase_names[scan_string_table_roots] = " Scan String Table Roots"; 412 _phase_names[scan_universe_roots] = " Scan Universe Roots"; 413 _phase_names[scan_jni_roots] = " Scan JNI Roots"; 414 _phase_names[scan_jni_weak_roots] = " Scan JNI Weak Roots"; 415 _phase_names[scan_synchronizer_roots] = " Scan Synchronizer Roots"; 416 _phase_names[scan_flat_profiler_roots] = " Scan Flat Profiler Roots"; 417 _phase_names[scan_management_roots] = " Scan Management Roots"; 418 _phase_names[scan_system_dictionary_roots] = " Scan System Dictionary Roots"; 419 _phase_names[scan_cldg_roots] = " Scan CLDG Roots"; 420 _phase_names[scan_jvmti_roots] = " Scan JVMTI Roots"; 421 422 _phase_names[update_thread_roots] = " Update Thread Roots"; 423 _phase_names[update_code_roots] = " Update Code Cache Roots"; 424 _phase_names[update_string_table_roots] = " Update String Table Roots"; 425 _phase_names[update_universe_roots] = " Update Universe Roots"; 426 _phase_names[update_jni_roots] = " Update JNI Roots"; 427 _phase_names[update_jni_weak_roots] = " Update JNI Weak Roots"; 428 _phase_names[update_synchronizer_roots] = " Update Synchronizer Roots"; 429 _phase_names[update_flat_profiler_roots] = " Update Flat Profiler Roots"; 430 _phase_names[update_management_roots] = " Update Management Roots"; 431 _phase_names[update_system_dictionary_roots] = " Update System Dictionary Roots"; 432 _phase_names[update_cldg_roots] = " Update CLDG Roots"; 433 _phase_names[update_jvmti_roots] = " Update JVMTI Roots"; 434 435 _phase_names[evac_thread_roots] = " Evacuate Thread Roots"; 436 _phase_names[evac_code_roots] = " Evacuate Code Cache Roots"; 437 _phase_names[evac_string_table_roots] = " Evacuate String Table Roots"; 438 _phase_names[evac_universe_roots] = " Evacuate Universe Roots"; 439 _phase_names[evac_jni_roots] = " Evacuate JNI Roots"; 440 _phase_names[evac_jni_weak_roots] = " Evacuate JNI Weak Roots"; 441 _phase_names[evac_synchronizer_roots] = " Evacuate Synchronizer Roots"; 442 _phase_names[evac_flat_profiler_roots] = " Evacuate Flat Profiler Roots"; 443 _phase_names[evac_management_roots] = " Evacuate Management Roots"; 444 _phase_names[evac_system_dictionary_roots] = " Evacuate System Dictionary Roots"; 445 _phase_names[evac_cldg_roots] = " Evacuate CLDG Roots"; 446 _phase_names[evac_jvmti_roots] = " Evacuate JVMTI Roots"; 447 448 _phase_names[recycle_regions] = " Recycle regions"; 449 _phase_names[reset_bitmaps] = "ResetBitmaps"; 450 _phase_names[resize_tlabs] = "Resize TLABs"; 451 452 _phase_names[full_gc] = "Full GC Times"; 453 _phase_names[full_gc_mark] = " Mark"; 454 _phase_names[full_gc_mark_weakrefs] = " Weak References"; 455 _phase_names[full_gc_mark_class_unloading] = " Class Unloading"; 456 _phase_names[full_gc_calculate_addresses] = " Calculate Addresses"; 457 _phase_names[full_gc_adjust_pointers] = " Adjust Pointers"; 458 _phase_names[full_gc_copy_objects] = " Copy Objects"; 459 460 _phase_names[conc_mark] = "Concurrent Marking Times"; 461 _phase_names[conc_evac] = "Concurrent Evacuation Times"; 462 463 if (ShenandoahGCHeuristics != NULL) { 464 if (strcmp(ShenandoahGCHeuristics, "aggressive") == 0) { 465 log_info(gc, init)("Shenandoah heuristics: aggressive"); 466 _heuristics = new AggressiveHeuristics(); 467 } else if (strcmp(ShenandoahGCHeuristics, "dynamic") == 0) { 468 log_info(gc, init)("Shenandoah heuristics: dynamic"); 469 _heuristics = new DynamicHeuristics(); 470 } else if (strcmp(ShenandoahGCHeuristics, "adaptive") == 0) { 471 log_info(gc, init)("Shenandoah heuristics: adaptive"); 472 _heuristics = new AdaptiveHeuristics(); 473 } else if (strcmp(ShenandoahGCHeuristics, "passive") == 0) { 474 log_info(gc, init)("Shenandoah heuristics: passive"); 475 _heuristics = new PassiveHeuristics(); 476 } else { 477 vm_exit_during_initialization("Unknown -XX:ShenandoahGCHeuristics option"); 478 } 479 } else { 480 ShouldNotReachHere(); 481 } 482 _phase_times = new ShenandoahPhaseTimes(MAX2(ConcGCThreads, ParallelGCThreads)); 483 } 484 485 ShenandoahCollectorPolicy* ShenandoahCollectorPolicy::as_pgc_policy() { 486 return this; 487 } 488 489 BarrierSet::Name ShenandoahCollectorPolicy::barrier_set_name() { 490 return BarrierSet::ShenandoahBarrierSet; 491 } 492 493 HeapWord* ShenandoahCollectorPolicy::mem_allocate_work(size_t size, 494 bool is_tlab, 495 bool* gc_overhead_limit_was_exceeded) { 496 guarantee(false, "Not using this policy feature yet."); 497 return NULL; 498 } 499 500 HeapWord* ShenandoahCollectorPolicy::satisfy_failed_allocation(size_t size, bool is_tlab) { 501 guarantee(false, "Not using this policy feature yet."); 502 return NULL; 503 } 504 505 void ShenandoahCollectorPolicy::initialize_alignments() { 506 507 // This is expected by our algorithm for ShenandoahHeap::heap_region_containing(). 508 _space_alignment = ShenandoahHeapRegion::RegionSizeBytes; 509 _heap_alignment = ShenandoahHeapRegion::RegionSizeBytes; 510 } 511 512 void ShenandoahCollectorPolicy::post_heap_initialize() { 513 // Nothing to do here (yet). 514 } 515 516 void ShenandoahCollectorPolicy::record_bytes_allocated(size_t bytes) { 517 _heuristics->record_bytes_allocated(bytes); 518 } 519 520 void ShenandoahCollectorPolicy::record_bytes_start_CM(size_t bytes) { 521 _heuristics->record_bytes_start_CM(bytes); 522 } 523 524 void ShenandoahCollectorPolicy::record_bytes_end_CM(size_t bytes) { 525 _heuristics->record_bytes_end_CM(bytes); 526 } 527 528 void ShenandoahCollectorPolicy::record_bytes_reclaimed(size_t bytes) { 529 _heuristics->record_bytes_reclaimed(bytes); 530 } 531 532 void ShenandoahCollectorPolicy::record_user_requested_gc() { 533 _user_requested_gcs++; 534 } 535 536 void ShenandoahCollectorPolicy::record_allocation_failure_gc() { 537 _allocation_failure_gcs++; 538 } 539 540 bool ShenandoahCollectorPolicy::should_start_concurrent_mark(size_t used, 541 size_t capacity) { 542 return _heuristics->should_start_concurrent_mark(used, capacity); 543 } 544 545 void ShenandoahCollectorPolicy::choose_collection_set(ShenandoahCollectionSet* collection_set) { 546 _heuristics->choose_collection_set(collection_set); 547 } 548 549 void ShenandoahCollectorPolicy::choose_free_set(ShenandoahFreeSet* free_set) { 550 _heuristics->choose_free_set(free_set); 551 } 552 553 554 bool ShenandoahCollectorPolicy::process_references() { 555 return _heuristics->process_references(); 556 } 557 558 bool ShenandoahCollectorPolicy::unload_classes() { 559 return _heuristics->unload_classes(); 560 } 561 562 void ShenandoahCollectorPolicy::print_tracing_info(outputStream* out) { 563 for (uint i = 0; i < _num_phases; i++) { 564 if (_timing_data[i]._ms.maximum() != 0) { 565 print_summary_sd(out, _phase_names[i], &(_timing_data[i]._ms)); 566 } 567 } 568 out->print_cr("User requested GCs: "SIZE_FORMAT, _user_requested_gcs); 569 out->print_cr("Allocation failure GCs: "SIZE_FORMAT, _allocation_failure_gcs); 570 571 out->print_cr(" "); 572 double total_sum = _timing_data[init_mark_gross]._ms.sum() + 573 _timing_data[final_mark_gross]._ms.sum(); 574 double total_avg = (_timing_data[init_mark_gross]._ms.avg() + 575 _timing_data[final_mark_gross]._ms.avg()) / 2.0; 576 double total_max = MAX2(_timing_data[init_mark_gross]._ms.maximum(), 577 _timing_data[final_mark_gross]._ms.maximum()); 578 579 out->print_cr("%-27s = %8.2lf s, avg = %8.2lf ms, max = %8.2lf ms", 580 "Total", total_sum / 1000.0, total_avg, total_max); 581 582 } 583 584 void ShenandoahCollectorPolicy::print_summary_sd(outputStream* out, const char* str, const NumberSeq* seq) { 585 double sum = seq->sum(); 586 out->print("%-34s = %8.2lf s (avg = %8.2lf ms)", 587 str, sum / 1000.0, seq->avg()); 588 out->print_cr(" %s = "INT32_FORMAT_W(5)", std dev = %8.2lf ms, max = %8.2lf ms)", 589 "(num", seq->num(), seq->sd(), seq->maximum()); 590 } 591 592 void ShenandoahCollectorPolicy::increase_cycle_counter() { 593 _cycle_counter++; 594 } 595 596 size_t ShenandoahCollectorPolicy::cycle_counter() const { 597 return _cycle_counter; 598 } 599 600 ShenandoahPhaseTimes* ShenandoahCollectorPolicy::phase_times() { 601 return _phase_times; 602 }