1 /*
2 * Copyright (c) 2017, 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 *
80 }
81
82 ShenandoahPhaseTimings::Phase ShenandoahPhaseTimings::worker_par_phase(Phase phase, ParPhase par_phase) {
83 assert(is_worker_phase(phase), "Phase should accept worker phase times: %s", phase_name(phase));
84 Phase p = Phase(phase + 1 + par_phase);
85 assert(p >= 0 && p < _num_phases, "Out of bound for: %s", phase_name(phase));
86 return p;
87 }
88
89 ShenandoahWorkerData* ShenandoahPhaseTimings::worker_data(Phase phase, ParPhase par_phase) {
90 Phase p = worker_par_phase(phase, par_phase);
91 ShenandoahWorkerData* wd = _worker_data[p];
92 assert(wd != nullptr, "Counter initialized: %s", phase_name(p));
93 return wd;
94 }
95
96 bool ShenandoahPhaseTimings::is_worker_phase(Phase phase) {
97 assert(phase >= 0 && phase < _num_phases, "Out of bounds");
98 switch (phase) {
99 case init_evac:
100 case finish_mark:
101 case purge_weak_par:
102 case full_gc_mark:
103 case full_gc_update_roots:
104 case full_gc_adjust_roots:
105 case degen_gc_stw_mark:
106 case degen_gc_mark:
107 case degen_gc_update_roots:
108 case full_gc_weakrefs:
109 case full_gc_purge_class_unload:
110 case full_gc_purge_weak_par:
111 case degen_gc_weakrefs:
112 case degen_gc_purge_class_unload:
113 case degen_gc_purge_weak_par:
114 case heap_iteration_roots:
115 case conc_mark_roots:
116 case conc_thread_roots:
117 case conc_weak_roots_work:
118 case conc_weak_refs:
119 case conc_strong_roots:
120 return true;
121 default:
122 return false;
123 }
124 }
125
126 bool ShenandoahPhaseTimings::is_root_work_phase(Phase phase) {
127 switch (phase) {
128 case finish_mark:
129 case init_evac:
130 case degen_gc_update_roots:
131 case full_gc_mark:
132 case full_gc_update_roots:
133 case full_gc_adjust_roots:
134 return true;
135 default:
136 return false;
137 }
138 }
139
168
169 #ifdef ASSERT
170 for (uint i = 1; i < _num_par_phases; i++) {
171 ShenandoahWorkerData* wd = worker_data(phase, ParPhase(i));
172 for (uint c = 0; c < _max_workers; c++) {
173 assert(wd->get(c) == ShenandoahWorkerData::uninitialized(),
174 "Should not be set: %s", phase_name(worker_par_phase(phase, ParPhase(i))));
175 }
176 }
177 #endif
178 }
179
180 void ShenandoahPhaseTimings::record_workers_end(Phase phase) {
181 assert(is_worker_phase(phase), "Phase should accept worker phase times: %s", phase_name(phase));
182 }
183
184 void ShenandoahPhaseTimings::flush_par_workers_to_cycle() {
185 for (uint pi = 0; pi < _num_phases; pi++) {
186 Phase phase = Phase(pi);
187 if (is_worker_phase(phase)) {
188 double s = uninitialized();
189 for (uint i = 1; i < _num_par_phases; i++) {
190 ShenandoahWorkerData* wd = worker_data(phase, ParPhase(i));
191 double ws = uninitialized();
192 for (uint c = 0; c < _max_workers; c++) {
193 double v = wd->get(c);
194 if (v != ShenandoahWorkerData::uninitialized()) {
195 if (ws == uninitialized()) {
196 ws = v;
197 } else {
198 ws += v;
199 }
200 }
201 }
202 if (ws != uninitialized()) {
203 // add to each line in phase
204 set_cycle_data(Phase(phase + i + 1), ws);
205 if (s == uninitialized()) {
206 s = ws;
207 } else {
208 s += ws;
209 }
210 }
211 }
212 if (s != uninitialized()) {
213 // add to total for phase
214 set_cycle_data(Phase(phase + 1), s);
215 }
216 }
217 }
218 }
219
220 void ShenandoahPhaseTimings::flush_cycle_to_global() {
221 for (uint i = 0; i < _num_phases; i++) {
222 if (_cycle_data[i] != uninitialized()) {
223 _global_data[i].add(_cycle_data[i]);
224 _cycle_data[i] = uninitialized();
225 }
226 if (_worker_data[i] != nullptr) {
227 _worker_data[i]->reset();
228 }
229 }
230 OrderAccess::fence();
231 }
232
233 void ShenandoahPhaseTimings::print_cycle_on(outputStream* out) const {
234 out->cr();
295 SHENANDOAH_US_TIME_FORMAT ", "
296 SHENANDOAH_US_TIME_FORMAT ", "
297 SHENANDOAH_US_TIME_FORMAT ", "
298 SHENANDOAH_US_TIME_FORMAT ", "
299 SHENANDOAH_US_TIME_FORMAT ")",
300 _phase_names[i],
301 _global_data[i].sum(),
302 _global_data[i].avg() * 1000000.0,
303 _global_data[i].num(),
304 _global_data[i].percentile(0) * 1000000.0,
305 _global_data[i].percentile(25) * 1000000.0,
306 _global_data[i].percentile(50) * 1000000.0,
307 _global_data[i].percentile(75) * 1000000.0,
308 _global_data[i].maximum() * 1000000.0
309 );
310 }
311 }
312 }
313
314 ShenandoahWorkerTimingsTracker::ShenandoahWorkerTimingsTracker(ShenandoahPhaseTimings::Phase phase,
315 ShenandoahPhaseTimings::ParPhase par_phase, uint worker_id) :
316 _timings(ShenandoahHeap::heap()->phase_timings()),
317 _phase(phase), _par_phase(par_phase), _worker_id(worker_id) {
318
319 assert(_timings->worker_data(_phase, _par_phase)->get(_worker_id) == ShenandoahWorkerData::uninitialized(),
320 "Should not be set yet: %s", ShenandoahPhaseTimings::phase_name(_timings->worker_par_phase(_phase, _par_phase)));
321 _start_time = os::elapsedTime();
322 }
323
324 ShenandoahWorkerTimingsTracker::~ShenandoahWorkerTimingsTracker() {
325 _timings->worker_data(_phase, _par_phase)->set(_worker_id, os::elapsedTime() - _start_time);
326
327 if (ShenandoahPhaseTimings::is_root_work_phase(_phase)) {
328 ShenandoahPhaseTimings::Phase root_phase = _phase;
329 ShenandoahPhaseTimings::Phase cur_phase = _timings->worker_par_phase(root_phase, _par_phase);
330 _event.commit(GCId::current(), _worker_id, ShenandoahPhaseTimings::phase_name(cur_phase));
331 }
332 }
|
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 *
81 }
82
83 ShenandoahPhaseTimings::Phase ShenandoahPhaseTimings::worker_par_phase(Phase phase, ParPhase par_phase) {
84 assert(is_worker_phase(phase), "Phase should accept worker phase times: %s", phase_name(phase));
85 Phase p = Phase(phase + 1 + par_phase);
86 assert(p >= 0 && p < _num_phases, "Out of bound for: %s", phase_name(phase));
87 return p;
88 }
89
90 ShenandoahWorkerData* ShenandoahPhaseTimings::worker_data(Phase phase, ParPhase par_phase) {
91 Phase p = worker_par_phase(phase, par_phase);
92 ShenandoahWorkerData* wd = _worker_data[p];
93 assert(wd != nullptr, "Counter initialized: %s", phase_name(p));
94 return wd;
95 }
96
97 bool ShenandoahPhaseTimings::is_worker_phase(Phase phase) {
98 assert(phase >= 0 && phase < _num_phases, "Out of bounds");
99 switch (phase) {
100 case init_evac:
101 case init_scan_rset:
102 case finish_mark:
103 case purge_weak_par:
104 case full_gc_mark:
105 case full_gc_update_roots:
106 case full_gc_adjust_roots:
107 case degen_gc_stw_mark:
108 case degen_gc_mark:
109 case degen_gc_update_roots:
110 case full_gc_weakrefs:
111 case full_gc_purge_class_unload:
112 case full_gc_purge_weak_par:
113 case degen_gc_coalesce_and_fill:
114 case degen_gc_weakrefs:
115 case degen_gc_purge_class_unload:
116 case degen_gc_purge_weak_par:
117 case heap_iteration_roots:
118 case conc_mark:
119 case conc_mark_roots:
120 case conc_thread_roots:
121 case conc_weak_roots_work:
122 case conc_weak_refs:
123 case conc_strong_roots:
124 case conc_coalesce_and_fill:
125 return true;
126 default:
127 return false;
128 }
129 }
130
131 bool ShenandoahPhaseTimings::is_root_work_phase(Phase phase) {
132 switch (phase) {
133 case finish_mark:
134 case init_evac:
135 case degen_gc_update_roots:
136 case full_gc_mark:
137 case full_gc_update_roots:
138 case full_gc_adjust_roots:
139 return true;
140 default:
141 return false;
142 }
143 }
144
173
174 #ifdef ASSERT
175 for (uint i = 1; i < _num_par_phases; i++) {
176 ShenandoahWorkerData* wd = worker_data(phase, ParPhase(i));
177 for (uint c = 0; c < _max_workers; c++) {
178 assert(wd->get(c) == ShenandoahWorkerData::uninitialized(),
179 "Should not be set: %s", phase_name(worker_par_phase(phase, ParPhase(i))));
180 }
181 }
182 #endif
183 }
184
185 void ShenandoahPhaseTimings::record_workers_end(Phase phase) {
186 assert(is_worker_phase(phase), "Phase should accept worker phase times: %s", phase_name(phase));
187 }
188
189 void ShenandoahPhaseTimings::flush_par_workers_to_cycle() {
190 for (uint pi = 0; pi < _num_phases; pi++) {
191 Phase phase = Phase(pi);
192 if (is_worker_phase(phase)) {
193 double sum = uninitialized();
194 for (uint i = 1; i < _num_par_phases; i++) {
195 ShenandoahWorkerData* wd = worker_data(phase, ParPhase(i));
196 double worker_sum = uninitialized();
197 for (uint c = 0; c < _max_workers; c++) {
198 double worker_time = wd->get(c);
199 if (worker_time != ShenandoahWorkerData::uninitialized()) {
200 if (worker_sum == uninitialized()) {
201 worker_sum = worker_time;
202 } else {
203 worker_sum += worker_time;
204 }
205 }
206 }
207 if (worker_sum != uninitialized()) {
208 // add to each line in phase
209 set_cycle_data(Phase(phase + i + 1), worker_sum);
210 if (sum == uninitialized()) {
211 sum = worker_sum;
212 } else {
213 sum += worker_sum;
214 }
215 }
216 }
217 if (sum != uninitialized()) {
218 // add to total for phase
219 set_cycle_data(Phase(phase + 1), sum);
220 }
221 }
222 }
223 }
224
225 void ShenandoahPhaseTimings::flush_cycle_to_global() {
226 for (uint i = 0; i < _num_phases; i++) {
227 if (_cycle_data[i] != uninitialized()) {
228 _global_data[i].add(_cycle_data[i]);
229 _cycle_data[i] = uninitialized();
230 }
231 if (_worker_data[i] != nullptr) {
232 _worker_data[i]->reset();
233 }
234 }
235 OrderAccess::fence();
236 }
237
238 void ShenandoahPhaseTimings::print_cycle_on(outputStream* out) const {
239 out->cr();
300 SHENANDOAH_US_TIME_FORMAT ", "
301 SHENANDOAH_US_TIME_FORMAT ", "
302 SHENANDOAH_US_TIME_FORMAT ", "
303 SHENANDOAH_US_TIME_FORMAT ", "
304 SHENANDOAH_US_TIME_FORMAT ")",
305 _phase_names[i],
306 _global_data[i].sum(),
307 _global_data[i].avg() * 1000000.0,
308 _global_data[i].num(),
309 _global_data[i].percentile(0) * 1000000.0,
310 _global_data[i].percentile(25) * 1000000.0,
311 _global_data[i].percentile(50) * 1000000.0,
312 _global_data[i].percentile(75) * 1000000.0,
313 _global_data[i].maximum() * 1000000.0
314 );
315 }
316 }
317 }
318
319 ShenandoahWorkerTimingsTracker::ShenandoahWorkerTimingsTracker(ShenandoahPhaseTimings::Phase phase,
320 ShenandoahPhaseTimings::ParPhase par_phase, uint worker_id, bool cumulative) :
321 _timings(ShenandoahHeap::heap()->phase_timings()),
322 _phase(phase), _par_phase(par_phase), _worker_id(worker_id) {
323
324 assert(_timings->worker_data(_phase, _par_phase)->get(_worker_id) == ShenandoahWorkerData::uninitialized() || cumulative,
325 "Should not be set yet: %s", ShenandoahPhaseTimings::phase_name(_timings->worker_par_phase(_phase, _par_phase)));
326 _start_time = os::elapsedTime();
327 }
328
329 ShenandoahWorkerTimingsTracker::~ShenandoahWorkerTimingsTracker() {
330 _timings->worker_data(_phase, _par_phase)->set_or_add(_worker_id, os::elapsedTime() - _start_time);
331
332 if (ShenandoahPhaseTimings::is_root_work_phase(_phase)) {
333 ShenandoahPhaseTimings::Phase root_phase = _phase;
334 ShenandoahPhaseTimings::Phase cur_phase = _timings->worker_par_phase(root_phase, _par_phase);
335 _event.commit(GCId::current(), _worker_id, ShenandoahPhaseTimings::phase_name(cur_phase));
336 }
337 }
|