1 /* 2 * Copyright (c) 2022, Amazon, 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 #include "precompiled.hpp" 25 26 #include "gc/shenandoah/shenandoahHeap.inline.hpp" 27 #include "gc/shenandoah/shenandoahEvacTracker.hpp" 28 #include "gc/shenandoah/shenandoahThreadLocalData.hpp" 29 #include "gc/shenandoah/shenandoahRootProcessor.hpp" 30 #include "runtime/threadSMR.inline.hpp" 31 #include "runtime/thread.hpp" 32 33 ShenandoahEvacuationStats::ShenandoahEvacuationStats() 34 : _evacuations_completed(0), _bytes_completed(0), 35 _evacuations_attempted(0), _bytes_attempted(0), 36 _age_table(false) {} 37 38 void ShenandoahEvacuationStats::begin_evacuation(size_t bytes) { 39 ++_evacuations_attempted; 40 _bytes_attempted += bytes; 41 } 42 43 void ShenandoahEvacuationStats::end_evacuation(size_t bytes, uint age) { 44 ++_evacuations_completed; 45 _bytes_completed += bytes; 46 if (age > 0) { 47 _age_table.add(age, bytes / oopSize); 48 } 49 } 50 51 void ShenandoahEvacuationStats::accumulate(const ShenandoahEvacuationStats* other) { 52 _evacuations_completed += other->_evacuations_completed; 53 _bytes_completed += other->_bytes_completed; 54 _evacuations_attempted += other->_evacuations_attempted; 55 _bytes_attempted += other->_bytes_attempted; 56 57 _age_table.merge(&other->_age_table); 58 } 59 60 void ShenandoahEvacuationStats::reset() { 61 _evacuations_completed = _evacuations_attempted = 0; 62 _bytes_completed = _bytes_attempted = 0; 63 _age_table.clear(); 64 } 65 66 void ShenandoahEvacuationStats::print_on(outputStream* st) { 67 size_t abandoned_size = _bytes_attempted - _bytes_completed; 68 size_t abandoned_count = _evacuations_attempted - _evacuations_completed; 69 st->print_cr("Evacuated " SIZE_FORMAT "%s across " SIZE_FORMAT " objects, " 70 "abandoned " SIZE_FORMAT "%s across " SIZE_FORMAT " objects.", 71 byte_size_in_proper_unit(_bytes_completed), 72 proper_unit_for_byte_size(_bytes_completed), _evacuations_completed, 73 byte_size_in_proper_unit(abandoned_size), 74 proper_unit_for_byte_size(abandoned_size), abandoned_count); 75 _age_table.print_on(st, InitialTenuringThreshold); 76 } 77 78 void ShenandoahEvacuationTracker::print_global_on(outputStream* st) { 79 print_evacuations_on(st, &_workers_global, &_mutators_global); 80 } 81 82 void ShenandoahEvacuationTracker::print_evacuations_on(outputStream* st, 83 ShenandoahEvacuationStats* workers, 84 ShenandoahEvacuationStats* mutators) { 85 st->print("Workers: "); 86 workers->print_on(st); 87 st->cr(); 88 st->print("Mutators: "); 89 mutators->print_on(st); 90 st->cr(); 91 92 AgeTable region_ages(false); 93 ShenandoahHeap* heap = ShenandoahHeap::heap(); 94 for (uint i = 0; i < heap->num_regions(); ++i) { 95 ShenandoahHeapRegion* r = heap->get_region(i); 96 if (r->age() > 0 && r->age() < AgeTable::table_size) { 97 region_ages.add(r->age(), r->get_live_data_words()); 98 } 99 } 100 st->print("Regions: "); 101 region_ages.print_on(st, InitialTenuringThreshold); 102 } 103 104 class ShenandoahStatAggregator : public ThreadClosure { 105 public: 106 ShenandoahEvacuationStats* _target; 107 explicit ShenandoahStatAggregator(ShenandoahEvacuationStats* target) : _target(target) {} 108 virtual void do_thread(Thread* thread) override { 109 ShenandoahEvacuationStats* local = ShenandoahThreadLocalData::evacuation_stats(thread); 110 _target->accumulate(local); 111 local->reset(); 112 } 113 }; 114 115 ShenandoahCycleStats ShenandoahEvacuationTracker::flush_cycle_to_global() { 116 ShenandoahEvacuationStats mutators, workers; 117 118 ThreadsListHandle java_threads_iterator; 119 ShenandoahStatAggregator aggregate_mutators(&mutators); 120 java_threads_iterator.list()->threads_do(&aggregate_mutators); 121 122 ShenandoahStatAggregator aggregate_workers(&workers); 123 ShenandoahHeap::heap()->gc_threads_do(&aggregate_workers); 124 125 _mutators_global.accumulate(&mutators); 126 _workers_global.accumulate(&workers); 127 128 return {workers, mutators}; 129 } 130 131 void ShenandoahEvacuationTracker::begin_evacuation(Thread* thread, size_t bytes) { 132 ShenandoahThreadLocalData::begin_evacuation(thread, bytes); 133 } 134 135 void ShenandoahEvacuationTracker::end_evacuation(Thread* thread, size_t bytes, uint age) { 136 ShenandoahThreadLocalData::end_evacuation(thread, bytes, age); 137 }