// 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
