blob: 862efda83e5b566923c15404357c45c0db09f13b [file] [log] [blame]
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
#include "src/isolate.h"
#include "src/utils.h"
namespace v8 {
namespace internal {
namespace {
double MonotonicallyIncreasingTimeInMs() {
return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() *
static_cast<double>(base::Time::kMillisecondsPerSecond);
}
const double kEstimatedRuntimeWithoutData = 1.0;
} // namespace
CompilerDispatcherTracer::Scope::Scope(CompilerDispatcherTracer* tracer,
ScopeID scope_id, size_t num)
: tracer_(tracer), scope_id_(scope_id), num_(num) {
start_time_ = MonotonicallyIncreasingTimeInMs();
}
CompilerDispatcherTracer::Scope::~Scope() {
double elapsed = MonotonicallyIncreasingTimeInMs() - start_time_;
switch (scope_id_) {
case ScopeID::kPrepare:
tracer_->RecordPrepare(elapsed);
break;
case ScopeID::kCompile:
tracer_->RecordCompile(elapsed, num_);
break;
case ScopeID::kFinalize:
tracer_->RecordFinalize(elapsed);
break;
}
}
// static
const char* CompilerDispatcherTracer::Scope::Name(ScopeID scope_id) {
switch (scope_id) {
case ScopeID::kPrepare:
return "V8.BackgroundCompile_Prepare";
case ScopeID::kCompile:
return "V8.BackgroundCompile_Compile";
case ScopeID::kFinalize:
return "V8.BackgroundCompile_Finalize";
}
UNREACHABLE();
}
CompilerDispatcherTracer::CompilerDispatcherTracer(Isolate* isolate)
: runtime_call_stats_(nullptr) {
// isolate might be nullptr during unittests.
if (isolate) {
runtime_call_stats_ = isolate->counters()->runtime_call_stats();
}
}
CompilerDispatcherTracer::~CompilerDispatcherTracer() {}
void CompilerDispatcherTracer::RecordPrepare(double duration_ms) {
base::LockGuard<base::Mutex> lock(&mutex_);
prepare_events_.Push(duration_ms);
}
void CompilerDispatcherTracer::RecordCompile(double duration_ms,
size_t source_length) {
base::LockGuard<base::Mutex> lock(&mutex_);
compile_events_.Push(std::make_pair(source_length, duration_ms));
}
void CompilerDispatcherTracer::RecordFinalize(double duration_ms) {
base::LockGuard<base::Mutex> lock(&mutex_);
finalize_events_.Push(duration_ms);
}
double CompilerDispatcherTracer::EstimatePrepareInMs() const {
base::LockGuard<base::Mutex> lock(&mutex_);
return Average(prepare_events_);
}
double CompilerDispatcherTracer::EstimateCompileInMs(
size_t source_length) const {
base::LockGuard<base::Mutex> lock(&mutex_);
return Estimate(compile_events_, source_length);
}
double CompilerDispatcherTracer::EstimateFinalizeInMs() const {
base::LockGuard<base::Mutex> lock(&mutex_);
return Average(finalize_events_);
}
void CompilerDispatcherTracer::DumpStatistics() const {
PrintF(
"CompilerDispatcherTracer: "
"prepare=%.2lfms compiling=%.2lfms/kb finalize=%.2lfms\n",
EstimatePrepareInMs(), EstimateCompileInMs(1 * KB),
EstimateFinalizeInMs());
}
double CompilerDispatcherTracer::Average(
const base::RingBuffer<double>& buffer) {
if (buffer.Count() == 0) return 0.0;
double sum = buffer.Sum([](double a, double b) { return a + b; }, 0.0);
return sum / buffer.Count();
}
double CompilerDispatcherTracer::Estimate(
const base::RingBuffer<std::pair<size_t, double>>& buffer, size_t num) {
if (buffer.Count() == 0) return kEstimatedRuntimeWithoutData;
std::pair<size_t, double> sum = buffer.Sum(
[](std::pair<size_t, double> a, std::pair<size_t, double> b) {
return std::make_pair(a.first + b.first, a.second + b.second);
},
std::make_pair(0, 0.0));
return num * (sum.second / sum.first);
}
} // namespace internal
} // namespace v8