1 /* 2 * Copyright (c) 2013, 2021, Red Hat, Inc. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 27 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" 28 #include "gc/shenandoah/shenandoahGC.hpp" 29 #include "gc/shenandoah/shenandoahHeap.inline.hpp" 30 #include "runtime/os.hpp" 31 32 ShenandoahCollectorPolicy::ShenandoahCollectorPolicy() : 33 _success_concurrent_gcs(0), 34 _abbreviated_concurrent_gcs(0), 35 _success_degenerated_gcs(0), 36 _abbreviated_degenerated_gcs(0), 37 _success_full_gcs(0), 38 _consecutive_degenerated_gcs(0), 39 _alloc_failure_degenerated(0), 40 _alloc_failure_degenerated_upgrade_to_full(0), 41 _alloc_failure_full(0) { 42 43 Copy::zero_to_bytes(_degen_point_counts, sizeof(size_t) * ShenandoahGC::_DEGENERATED_LIMIT); 44 Copy::zero_to_bytes(_collection_cause_counts, sizeof(size_t) * GCCause::_last_gc_cause); 45 46 _tracer = new ShenandoahTracer(); 47 } 48 49 void ShenandoahCollectorPolicy::record_collection_cause(GCCause::Cause cause) { 50 assert(cause < GCCause::_last_gc_cause, "Invalid GCCause"); 51 _collection_cause_counts[cause]++; 52 } 53 54 void ShenandoahCollectorPolicy::record_alloc_failure_to_full() { 55 _alloc_failure_full++; 56 } 57 58 void ShenandoahCollectorPolicy::record_alloc_failure_to_degenerated(ShenandoahGC::ShenandoahDegenPoint point) { 59 assert(point < ShenandoahGC::_DEGENERATED_LIMIT, "sanity"); 60 _alloc_failure_degenerated++; 61 _degen_point_counts[point]++; 62 } 63 64 void ShenandoahCollectorPolicy::record_degenerated_upgrade_to_full() { 65 _consecutive_degenerated_gcs = 0; 66 _alloc_failure_degenerated_upgrade_to_full++; 67 } 68 69 void ShenandoahCollectorPolicy::record_success_concurrent(bool is_abbreviated) { 70 _consecutive_degenerated_gcs = 0; 71 _success_concurrent_gcs++; 72 if (is_abbreviated) { 73 _abbreviated_concurrent_gcs++; 74 } 75 } 76 77 void ShenandoahCollectorPolicy::record_success_degenerated(bool is_abbreviated) { 78 _success_degenerated_gcs++; 79 _consecutive_degenerated_gcs++; 80 if (is_abbreviated) { 81 _abbreviated_degenerated_gcs++; 82 } 83 } 84 85 void ShenandoahCollectorPolicy::record_success_full() { 86 _consecutive_degenerated_gcs = 0; 87 _success_full_gcs++; 88 } 89 90 void ShenandoahCollectorPolicy::record_shutdown() { 91 _in_shutdown.set(); 92 } 93 94 bool ShenandoahCollectorPolicy::is_at_shutdown() { 95 return _in_shutdown.is_set(); 96 } 97 98 bool is_explicit_gc(GCCause::Cause cause) { 99 return GCCause::is_user_requested_gc(cause) 100 || GCCause::is_serviceability_requested_gc(cause); 101 } 102 103 bool is_implicit_gc(GCCause::Cause cause) { 104 return cause != GCCause::_allocation_failure 105 && cause != GCCause::_shenandoah_concurrent_gc 106 && !is_explicit_gc(cause); 107 } 108 109 #ifdef ASSERT 110 bool is_valid_request(GCCause::Cause cause) { 111 return is_explicit_gc(cause) 112 || cause == GCCause::_metadata_GC_clear_soft_refs 113 || cause == GCCause::_codecache_GC_aggressive 114 || cause == GCCause::_codecache_GC_threshold 115 || cause == GCCause::_full_gc_alot 116 || cause == GCCause::_wb_young_gc 117 || cause == GCCause::_wb_full_gc 118 || cause == GCCause::_wb_breakpoint 119 || cause == GCCause::_scavenge_alot; 120 } 121 #endif 122 123 bool ShenandoahCollectorPolicy::should_run_full_gc(GCCause::Cause cause) { 124 return is_explicit_gc(cause) ? !ExplicitGCInvokesConcurrent : !ShenandoahImplicitGCInvokesConcurrent; 125 } 126 127 bool ShenandoahCollectorPolicy::should_handle_requested_gc(GCCause::Cause cause) { 128 assert(is_valid_request(cause), "only requested GCs here: %s", GCCause::to_string(cause)); 129 130 if (DisableExplicitGC) { 131 return !is_explicit_gc(cause); 132 } 133 return true; 134 } 135 136 void ShenandoahCollectorPolicy::print_gc_stats(outputStream* out) const { 137 out->print_cr("Under allocation pressure, concurrent cycles may cancel, and either continue cycle"); 138 out->print_cr("under stop-the-world pause or result in stop-the-world Full GC. Increase heap size,"); 139 out->print_cr("tune GC heuristics, set more aggressive pacing delay, or lower allocation rate"); 140 out->print_cr("to avoid Degenerated and Full GC cycles. Abbreviated cycles are those which found"); 141 out->print_cr("enough regions with no live objects to skip evacuation."); 142 out->cr(); 143 144 size_t completed_gcs = _success_full_gcs + _success_degenerated_gcs + _success_concurrent_gcs; 145 out->print_cr(SIZE_FORMAT_W(5) " Completed GCs", completed_gcs); 146 147 size_t explicit_requests = 0; 148 size_t implicit_requests = 0; 149 for (int c = 0; c < GCCause::_last_gc_cause; c++) { 150 size_t cause_count = _collection_cause_counts[c]; 151 if (cause_count > 0) { 152 auto cause = (GCCause::Cause) c; 153 if (is_explicit_gc(cause)) { 154 explicit_requests += cause_count; 155 } else if (is_implicit_gc(cause)) { 156 implicit_requests += cause_count; 157 } 158 const char* desc = GCCause::to_string(cause); 159 out->print_cr(" " SIZE_FORMAT_W(5) " caused by %s (%.2f%%)", cause_count, desc, percent_of(cause_count, completed_gcs)); 160 } 161 } 162 163 out->cr(); 164 out->print_cr(SIZE_FORMAT_W(5) " Successful Concurrent GCs (%.2f%%)", _success_concurrent_gcs, percent_of(_success_concurrent_gcs, completed_gcs)); 165 if (ExplicitGCInvokesConcurrent) { 166 out->print_cr(" " SIZE_FORMAT_W(5) " invoked explicitly (%.2f%%)", explicit_requests, percent_of(explicit_requests, _success_concurrent_gcs)); 167 } 168 if (ShenandoahImplicitGCInvokesConcurrent) { 169 out->print_cr(" " SIZE_FORMAT_W(5) " invoked implicitly (%.2f%%)", implicit_requests, percent_of(implicit_requests, _success_concurrent_gcs)); 170 } 171 out->print_cr(" " SIZE_FORMAT_W(5) " abbreviated (%.2f%%)", _abbreviated_concurrent_gcs, percent_of(_abbreviated_concurrent_gcs, _success_concurrent_gcs)); 172 out->cr(); 173 174 size_t degenerated_gcs = _alloc_failure_degenerated_upgrade_to_full + _success_degenerated_gcs; 175 out->print_cr(SIZE_FORMAT_W(5) " Degenerated GCs (%.2f%%)", degenerated_gcs, percent_of(degenerated_gcs, completed_gcs)); 176 out->print_cr(" " SIZE_FORMAT_W(5) " upgraded to Full GC (%.2f%%)", _alloc_failure_degenerated_upgrade_to_full, percent_of(_alloc_failure_degenerated_upgrade_to_full, degenerated_gcs)); 177 out->print_cr(" " SIZE_FORMAT_W(5) " caused by allocation failure (%.2f%%)", _alloc_failure_degenerated, percent_of(_alloc_failure_degenerated, degenerated_gcs)); 178 out->print_cr(" " SIZE_FORMAT_W(5) " abbreviated (%.2f%%)", _abbreviated_degenerated_gcs, percent_of(_abbreviated_degenerated_gcs, degenerated_gcs)); 179 for (int c = 0; c < ShenandoahGC::_DEGENERATED_LIMIT; c++) { 180 if (_degen_point_counts[c] > 0) { 181 const char* desc = ShenandoahGC::degen_point_to_string((ShenandoahGC::ShenandoahDegenPoint)c); 182 out->print_cr(" " SIZE_FORMAT_W(5) " happened at %s", _degen_point_counts[c], desc); 183 } 184 } 185 out->cr(); 186 187 out->print_cr(SIZE_FORMAT_W(5) " Full GCs (%.2f%%)", _success_full_gcs, percent_of(_success_full_gcs, completed_gcs)); 188 if (!ExplicitGCInvokesConcurrent) { 189 out->print_cr(" " SIZE_FORMAT_W(5) " invoked explicitly (%.2f%%)", explicit_requests, percent_of(explicit_requests, _success_concurrent_gcs)); 190 } 191 if (!ShenandoahImplicitGCInvokesConcurrent) { 192 out->print_cr(" " SIZE_FORMAT_W(5) " invoked implicitly (%.2f%%)", implicit_requests, percent_of(implicit_requests, _success_concurrent_gcs)); 193 } 194 out->print_cr(" " SIZE_FORMAT_W(5) " caused by allocation failure (%.2f%%)", _alloc_failure_full, percent_of(_alloc_failure_full, _success_full_gcs)); 195 out->print_cr(" " SIZE_FORMAT_W(5) " upgraded from Degenerated GC (%.2f%%)", _alloc_failure_degenerated_upgrade_to_full, percent_of(_alloc_failure_degenerated_upgrade_to_full, _success_full_gcs)); 196 }