Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files
8240671: Shenandoah: refactor ShenandoahPhaseTimings
Reviewed-by: rkennke, zgu
  • Loading branch information
shipilev committed Mar 6, 2020
1 parent c92adf4 commit d8bded6fb4b9b0266f64f0448fc27a68cee6e14f
@@ -41,8 +41,8 @@
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
#include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
#include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
#include "gc/shenandoah/shenandoahTaskqueue.inline.hpp"
#include "gc/shenandoah/shenandoahTimingTracker.hpp"
#include "gc/shenandoah/shenandoahUtils.hpp"

#include "memory/iterator.inline.hpp"
@@ -41,37 +41,30 @@ const char* ShenandoahPhaseTimings::_phase_names[] = {

#undef GC_PHASE_DECLARE_NAME

ShenandoahPhaseTimings::ShenandoahPhaseTimings() : _policy(NULL) {
ShenandoahPhaseTimings::ShenandoahPhaseTimings() {
uint max_workers = MAX2(ConcGCThreads, ParallelGCThreads);
_worker_times = new ShenandoahWorkerTimings(max_workers);
_policy = ShenandoahHeap::heap()->shenandoah_policy();
assert(_policy != NULL, "Can not be NULL");
}
assert(max_workers > 0, "Must have some GC threads");

void ShenandoahPhaseTimings::record_phase_start(Phase phase) {
_timing_data[phase]._start = os::elapsedTime();
}
#define GC_PAR_PHASE_DECLARE_WORKER_DATA(type, title) \
_gc_par_phases[ShenandoahPhaseTimings::type] = new WorkerDataArray<double>(title, max_workers);
// Root scanning phases
SHENANDOAH_GC_PAR_PHASE_DO(,, GC_PAR_PHASE_DECLARE_WORKER_DATA)
#undef GC_PAR_PHASE_DECLARE_WORKER_DATA

void ShenandoahPhaseTimings::record_phase_end(Phase phase) {
assert(_policy != NULL, "Not yet initialized");
double end = os::elapsedTime();
double elapsed = end - _timing_data[phase]._start;
if (!_policy->is_at_shutdown()) {
_timing_data[phase]._secs.add(elapsed);
}
ShenandoahHeap::heap()->heuristics()->record_phase_time(phase, elapsed);
_policy = ShenandoahHeap::heap()->shenandoah_policy();
assert(_policy != NULL, "Can not be NULL");
}

void ShenandoahPhaseTimings::record_phase_time(Phase phase, double time) {
assert(_policy != NULL, "Not yet initialized");
if (!_policy->is_at_shutdown()) {
_timing_data[phase]._secs.add(time);
_timing_data[phase].add(time);
}
ShenandoahHeap::heap()->heuristics()->record_phase_time(phase, time);
}

void ShenandoahPhaseTimings::record_workers_start(Phase phase) {
for (uint i = 0; i < GCParPhasesSentinel; i++) {
_worker_times->reset(i);
_gc_par_phases[i]->reset();
}
}

@@ -97,8 +90,8 @@ void ShenandoahPhaseTimings::record_workers_end(Phase phase) {
if (phase != _num_phases) {
// Merge _phase_time to counters below the given phase.
for (uint i = 0; i < GCParPhasesSentinel; i++) {
double t = _worker_times->average(i);
_timing_data[phase + i + 1]._secs.add(t);
double t = _gc_par_phases[i]->average();
_timing_data[phase + i + 1].add(t);
}
}
}
@@ -114,53 +107,38 @@ void ShenandoahPhaseTimings::print_on(outputStream* out) const {
out->cr();

for (uint i = 0; i < _num_phases; i++) {
if (_timing_data[i]._secs.maximum() != 0) {
print_summary_sd(out, _phase_names[i], &(_timing_data[i]._secs));
if (_timing_data[i].maximum() != 0) {
out->print_cr("%-27s = %8.2lf s (a = %8.0lf us) (n = " INT32_FORMAT_W(5) ") (lvls, us = %8.0lf, %8.0lf, %8.0lf, %8.0lf, %8.0lf)",
_phase_names[i],
_timing_data[i].sum(),
_timing_data[i].avg() * 1000000.0,
_timing_data[i].num(),
_timing_data[i].percentile(0) * 1000000.0,
_timing_data[i].percentile(25) * 1000000.0,
_timing_data[i].percentile(50) * 1000000.0,
_timing_data[i].percentile(75) * 1000000.0,
_timing_data[i].maximum() * 1000000.0
);
}
}
}

void ShenandoahPhaseTimings::print_summary_sd(outputStream* out, const char* str, const HdrSeq* seq) const {
out->print_cr("%-27s = %8.2lf s (a = %8.0lf us) (n = " INT32_FORMAT_W(5) ") (lvls, us = %8.0lf, %8.0lf, %8.0lf, %8.0lf, %8.0lf)",
str,
seq->sum(),
seq->avg() * 1000000.0,
seq->num(),
seq->percentile(0) * 1000000.0,
seq->percentile(25) * 1000000.0,
seq->percentile(50) * 1000000.0,
seq->percentile(75) * 1000000.0,
seq->maximum() * 1000000.0
);
void ShenandoahPhaseTimings::record_worker_time(ShenandoahPhaseTimings::GCParPhases phase, uint worker_id, double secs) {
_gc_par_phases[phase]->set(worker_id, secs);
}

ShenandoahWorkerTimings::ShenandoahWorkerTimings(uint max_gc_threads) :
_max_gc_threads(max_gc_threads)
{
assert(max_gc_threads > 0, "Must have some GC threads");

#define GC_PAR_PHASE_DECLARE_WORKER_DATA(type, title) \
_gc_par_phases[ShenandoahPhaseTimings::type] = new WorkerDataArray<double>(title, max_gc_threads);
// Root scanning phases
SHENANDOAH_GC_PAR_PHASE_DO(GC_PAR_PHASE_DECLARE_WORKER_DATA)
#undef GC_PAR_PHASE_DECLARE_WORKER_DATA
}

// record the time a phase took in seconds
void ShenandoahWorkerTimings::record_time_secs(ShenandoahPhaseTimings::GCParPhases phase, uint worker_i, double secs) {
_gc_par_phases[phase]->set(worker_i, secs);
ShenandoahWorkerTimingsTracker::ShenandoahWorkerTimingsTracker(ShenandoahPhaseTimings::GCParPhases phase, uint worker_id) :
_phase(phase), _timings(ShenandoahHeap::heap()->phase_timings()), _worker_id(worker_id) {
_start_time = os::elapsedTime();
}

double ShenandoahWorkerTimings::average(uint i) const {
return _gc_par_phases[i]->average();
}
ShenandoahWorkerTimingsTracker::~ShenandoahWorkerTimingsTracker() {
_timings->record_worker_time(_phase, _worker_id, os::elapsedTime() - _start_time);

void ShenandoahWorkerTimings::reset(uint i) {
_gc_par_phases[i]->reset();
}

void ShenandoahWorkerTimings::print() const {
for (uint i = 0; i < ShenandoahPhaseTimings::GCParPhasesSentinel; i++) {
_gc_par_phases[i]->print_summary_on(tty);
if (ShenandoahGCPhase::is_root_work_phase()) {
ShenandoahPhaseTimings::Phase root_phase = ShenandoahGCPhase::current_phase();
ShenandoahPhaseTimings::Phase cur_phase = (ShenandoahPhaseTimings::Phase)((int)root_phase + (int)_phase + 1);
_event.commit(GCId::current(), _worker_id, ShenandoahPhaseTimings::phase_name(cur_phase));
}
}

0 comments on commit d8bded6

Please sign in to comment.