1 /* 2 * Copyright (c) 2017, 2021, Red Hat, Inc. All rights reserved. 3 * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #include "precompiled.hpp" 27 28 #include "jfr/jfrEvents.hpp" 29 #include "gc/shared/gcCause.hpp" 30 #include "gc/shared/gcTrace.hpp" 31 #include "gc/shared/gcWhen.hpp" 32 #include "gc/shared/referenceProcessorStats.hpp" 33 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" 34 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" 35 #include "gc/shenandoah/shenandoahHeap.inline.hpp" 36 #include "gc/shenandoah/shenandoahOldGeneration.hpp" 37 #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" 38 #include "gc/shenandoah/shenandoahUtils.hpp" 39 #include "gc/shenandoah/shenandoahYoungGeneration.hpp" 40 #include "utilities/debug.hpp" 41 42 ShenandoahPhaseTimings::Phase ShenandoahTimingsTracker::_current_phase = ShenandoahPhaseTimings::_invalid_phase; 43 44 ShenandoahGCSession::ShenandoahGCSession(GCCause::Cause cause, ShenandoahGeneration* generation) : 45 _heap(ShenandoahHeap::heap()), 46 _generation(generation), 47 _timer(_heap->gc_timer()), 48 _tracer(_heap->tracer()) { 49 assert(!ShenandoahGCPhase::is_current_phase_valid(), "No current GC phase"); 50 51 _heap->on_cycle_start(cause, _generation); 52 53 _timer->register_gc_start(); 54 _tracer->report_gc_start(cause, _timer->gc_start()); 55 _heap->trace_heap_before_gc(_tracer); 56 57 _trace_cycle.initialize(_heap->cycle_memory_manager(), cause, 58 "end of GC cycle", 59 /* allMemoryPoolsAffected */ true, 60 /* recordGCBeginTime = */ true, 61 /* recordPreGCUsage = */ true, 62 /* recordPeakUsage = */ true, 63 /* recordPostGCUsage = */ true, 64 /* recordAccumulatedGCTime = */ true, 65 /* recordGCEndTime = */ true, 66 /* countCollection = */ true 67 ); 68 } 69 70 ShenandoahGCSession::~ShenandoahGCSession() { 71 _heap->on_cycle_end(_generation); 72 _timer->register_gc_end(); 73 _heap->trace_heap_after_gc(_tracer); 74 _tracer->report_gc_reference_stats(_generation->ref_processor()->reference_process_stats()); 75 _tracer->report_gc_end(_timer->gc_end(), _timer->time_partitions()); 76 assert(!ShenandoahGCPhase::is_current_phase_valid(), "No current GC phase"); 77 } 78 79 ShenandoahGCPauseMark::ShenandoahGCPauseMark(uint gc_id, const char* notification_message, SvcGCMarker::reason_type type) : 80 _heap(ShenandoahHeap::heap()), _gc_id_mark(gc_id), _svc_gc_mark(type), _is_gc_active_mark() { 81 _trace_pause.initialize(_heap->stw_memory_manager(), _heap->gc_cause(), 82 notification_message, 83 /* allMemoryPoolsAffected */ true, 84 /* recordGCBeginTime = */ true, 85 /* recordPreGCUsage = */ false, 86 /* recordPeakUsage = */ false, 87 /* recordPostGCUsage = */ false, 88 /* recordAccumulatedGCTime = */ true, 89 /* recordGCEndTime = */ true, 90 /* countCollection = */ true 91 ); 92 } 93 94 ShenandoahPausePhase::ShenandoahPausePhase(const char* title, ShenandoahPhaseTimings::Phase phase, bool log_heap_usage) : 95 ShenandoahTimingsTracker(phase), 96 _tracer(title, nullptr, GCCause::_no_gc, log_heap_usage), 97 _timer(ShenandoahHeap::heap()->gc_timer()) { 98 _timer->register_gc_pause_start(title); 99 } 100 101 ShenandoahPausePhase::~ShenandoahPausePhase() { 102 _timer->register_gc_pause_end(); 103 } 104 105 ShenandoahConcurrentPhase::ShenandoahConcurrentPhase(const char* title, ShenandoahPhaseTimings::Phase phase, bool log_heap_usage) : 106 ShenandoahTimingsTracker(phase), 107 _tracer(title, nullptr, GCCause::_no_gc, log_heap_usage), 108 _timer(ShenandoahHeap::heap()->gc_timer()) { 109 _timer->register_gc_concurrent_start(title); 110 } 111 112 ShenandoahConcurrentPhase::~ShenandoahConcurrentPhase() { 113 _timer->register_gc_concurrent_end(); 114 } 115 116 ShenandoahTimingsTracker::ShenandoahTimingsTracker(ShenandoahPhaseTimings::Phase phase, bool should_aggregate) : 117 _timings(ShenandoahHeap::heap()->phase_timings()), _phase(phase), _should_aggregate(should_aggregate) { 118 assert(Thread::current()->is_VM_thread() || Thread::current()->is_ConcurrentGC_thread(), 119 "Must be set by these threads"); 120 _parent_phase = _current_phase; 121 _current_phase = phase; 122 _start = os::elapsedTime(); 123 } 124 125 ShenandoahTimingsTracker::~ShenandoahTimingsTracker() { 126 _timings->record_phase_time(_phase, os::elapsedTime() - _start, _should_aggregate); 127 _current_phase = _parent_phase; 128 } 129 130 bool ShenandoahTimingsTracker::is_current_phase_valid() { 131 return _current_phase < ShenandoahPhaseTimings::_num_phases; 132 } 133 134 ShenandoahGCPhase::ShenandoahGCPhase(ShenandoahPhaseTimings::Phase phase) : 135 ShenandoahTimingsTracker(phase), 136 _timer(ShenandoahHeap::heap()->gc_timer()) { 137 _timer->register_gc_phase_start(ShenandoahPhaseTimings::phase_name(phase), Ticks::now()); 138 } 139 140 ShenandoahGCPhase::~ShenandoahGCPhase() { 141 _timer->register_gc_phase_end(Ticks::now()); 142 } 143 144 ShenandoahGCWorkerPhase::ShenandoahGCWorkerPhase(const ShenandoahPhaseTimings::Phase phase) : 145 _timings(ShenandoahHeap::heap()->phase_timings()), _phase(phase) { 146 _timings->record_workers_start(_phase); 147 } 148 149 ShenandoahGCWorkerPhase::~ShenandoahGCWorkerPhase() { 150 _timings->record_workers_end(_phase); 151 } 152 153 ShenandoahWorkerSession::ShenandoahWorkerSession(uint worker_id) { 154 assert(worker_id == WorkerThread::worker_id(), "Wrong worker id"); 155 } 156 157 ShenandoahConcurrentWorkerSession::~ShenandoahConcurrentWorkerSession() { 158 _event.commit(GCId::current(), ShenandoahPhaseTimings::phase_name(ShenandoahGCPhase::current_phase())); 159 } 160 161 ShenandoahParallelWorkerSession::~ShenandoahParallelWorkerSession() { 162 _event.commit(GCId::current(), WorkerThread::worker_id(), ShenandoahPhaseTimings::phase_name(ShenandoahGCPhase::current_phase())); 163 }