Home | History | Annotate | Download | only in compiler-dispatcher
      1 // Copyright 2016 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
      6 
      7 #include "src/isolate.h"
      8 #include "src/utils.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 
     13 namespace {
     14 
     15 double MonotonicallyIncreasingTimeInMs() {
     16   return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() *
     17          static_cast<double>(base::Time::kMillisecondsPerSecond);
     18 }
     19 
     20 const double kEstimatedRuntimeWithoutData = 1.0;
     21 
     22 }  // namespace
     23 
     24 CompilerDispatcherTracer::Scope::Scope(CompilerDispatcherTracer* tracer,
     25                                        ScopeID scope_id, size_t num)
     26     : tracer_(tracer), scope_id_(scope_id), num_(num) {
     27   start_time_ = MonotonicallyIncreasingTimeInMs();
     28 }
     29 
     30 CompilerDispatcherTracer::Scope::~Scope() {
     31   double elapsed = MonotonicallyIncreasingTimeInMs() - start_time_;
     32   switch (scope_id_) {
     33     case ScopeID::kPrepareToParse:
     34       tracer_->RecordPrepareToParse(elapsed);
     35       break;
     36     case ScopeID::kParse:
     37       tracer_->RecordParse(elapsed, num_);
     38       break;
     39     case ScopeID::kFinalizeParsing:
     40       tracer_->RecordFinalizeParsing(elapsed);
     41       break;
     42     case ScopeID::kAnalyze:
     43       tracer_->RecordAnalyze(elapsed);
     44       break;
     45     case ScopeID::kPrepareToCompile:
     46       tracer_->RecordPrepareToCompile(elapsed);
     47       break;
     48     case ScopeID::kCompile:
     49       tracer_->RecordCompile(elapsed, num_);
     50       break;
     51     case ScopeID::kFinalizeCompiling:
     52       tracer_->RecordFinalizeCompiling(elapsed);
     53       break;
     54   }
     55 }
     56 
     57 // static
     58 const char* CompilerDispatcherTracer::Scope::Name(ScopeID scope_id) {
     59   switch (scope_id) {
     60     case ScopeID::kPrepareToParse:
     61       return "V8.BackgroundCompile_PrepareToParse";
     62     case ScopeID::kParse:
     63       return "V8.BackgroundCompile_Parse";
     64     case ScopeID::kFinalizeParsing:
     65       return "V8.BackgroundCompile_FinalizeParsing";
     66     case ScopeID::kAnalyze:
     67       return "V8.BackgroundCompile_Analyze";
     68     case ScopeID::kPrepareToCompile:
     69       return "V8.BackgroundCompile_PrepareToCompile";
     70     case ScopeID::kCompile:
     71       return "V8.BackgroundCompile_Compile";
     72     case ScopeID::kFinalizeCompiling:
     73       return "V8.BackgroundCompile_FinalizeCompiling";
     74   }
     75   UNREACHABLE();
     76   return nullptr;
     77 }
     78 
     79 CompilerDispatcherTracer::CompilerDispatcherTracer(Isolate* isolate)
     80     : runtime_call_stats_(nullptr) {
     81   // isolate might be nullptr during unittests.
     82   if (isolate) {
     83     runtime_call_stats_ = isolate->counters()->runtime_call_stats();
     84   }
     85 }
     86 
     87 CompilerDispatcherTracer::~CompilerDispatcherTracer() {}
     88 
     89 void CompilerDispatcherTracer::RecordPrepareToParse(double duration_ms) {
     90   base::LockGuard<base::Mutex> lock(&mutex_);
     91   prepare_parse_events_.Push(duration_ms);
     92 }
     93 
     94 void CompilerDispatcherTracer::RecordParse(double duration_ms,
     95                                            size_t source_length) {
     96   base::LockGuard<base::Mutex> lock(&mutex_);
     97   parse_events_.Push(std::make_pair(source_length, duration_ms));
     98 }
     99 
    100 void CompilerDispatcherTracer::RecordFinalizeParsing(double duration_ms) {
    101   base::LockGuard<base::Mutex> lock(&mutex_);
    102   finalize_parsing_events_.Push(duration_ms);
    103 }
    104 
    105 void CompilerDispatcherTracer::RecordAnalyze(double duration_ms) {
    106   base::LockGuard<base::Mutex> lock(&mutex_);
    107   analyze_events_.Push(duration_ms);
    108 }
    109 
    110 void CompilerDispatcherTracer::RecordPrepareToCompile(double duration_ms) {
    111   base::LockGuard<base::Mutex> lock(&mutex_);
    112   prepare_compile_events_.Push(duration_ms);
    113 }
    114 
    115 void CompilerDispatcherTracer::RecordCompile(double duration_ms,
    116                                              size_t ast_size_in_bytes) {
    117   base::LockGuard<base::Mutex> lock(&mutex_);
    118   compile_events_.Push(std::make_pair(ast_size_in_bytes, duration_ms));
    119 }
    120 
    121 void CompilerDispatcherTracer::RecordFinalizeCompiling(double duration_ms) {
    122   base::LockGuard<base::Mutex> lock(&mutex_);
    123   finalize_compiling_events_.Push(duration_ms);
    124 }
    125 
    126 double CompilerDispatcherTracer::EstimatePrepareToParseInMs() const {
    127   base::LockGuard<base::Mutex> lock(&mutex_);
    128   return Average(prepare_parse_events_);
    129 }
    130 
    131 double CompilerDispatcherTracer::EstimateParseInMs(size_t source_length) const {
    132   base::LockGuard<base::Mutex> lock(&mutex_);
    133   return Estimate(parse_events_, source_length);
    134 }
    135 
    136 double CompilerDispatcherTracer::EstimateFinalizeParsingInMs() const {
    137   base::LockGuard<base::Mutex> lock(&mutex_);
    138   return Average(finalize_parsing_events_);
    139 }
    140 
    141 double CompilerDispatcherTracer::EstimateAnalyzeInMs() const {
    142   base::LockGuard<base::Mutex> lock(&mutex_);
    143   return Average(analyze_events_);
    144 }
    145 
    146 double CompilerDispatcherTracer::EstimatePrepareToCompileInMs() const {
    147   base::LockGuard<base::Mutex> lock(&mutex_);
    148   return Average(prepare_compile_events_);
    149 }
    150 
    151 double CompilerDispatcherTracer::EstimateCompileInMs(
    152     size_t ast_size_in_bytes) const {
    153   base::LockGuard<base::Mutex> lock(&mutex_);
    154   return Estimate(compile_events_, ast_size_in_bytes);
    155 }
    156 
    157 double CompilerDispatcherTracer::EstimateFinalizeCompilingInMs() const {
    158   base::LockGuard<base::Mutex> lock(&mutex_);
    159   return Average(finalize_compiling_events_);
    160 }
    161 
    162 void CompilerDispatcherTracer::DumpStatistics() const {
    163   PrintF(
    164       "CompilerDispatcherTracer: "
    165       "prepare_parsing=%.2lfms parsing=%.2lfms/kb finalize_parsing=%.2lfms "
    166       "analyze=%.2lfms prepare_compiling=%.2lfms compiling=%.2lfms/kb "
    167       "finalize_compiling=%.2lfms\n",
    168       EstimatePrepareToParseInMs(), EstimateParseInMs(1 * KB),
    169       EstimateFinalizeParsingInMs(), EstimateAnalyzeInMs(),
    170       EstimatePrepareToCompileInMs(), EstimateCompileInMs(1 * KB),
    171       EstimateFinalizeCompilingInMs());
    172 }
    173 
    174 double CompilerDispatcherTracer::Average(
    175     const base::RingBuffer<double>& buffer) {
    176   if (buffer.Count() == 0) return 0.0;
    177   double sum = buffer.Sum([](double a, double b) { return a + b; }, 0.0);
    178   return sum / buffer.Count();
    179 }
    180 
    181 double CompilerDispatcherTracer::Estimate(
    182     const base::RingBuffer<std::pair<size_t, double>>& buffer, size_t num) {
    183   if (buffer.Count() == 0) return kEstimatedRuntimeWithoutData;
    184   std::pair<size_t, double> sum = buffer.Sum(
    185       [](std::pair<size_t, double> a, std::pair<size_t, double> b) {
    186         return std::make_pair(a.first + b.first, a.second + b.second);
    187       },
    188       std::make_pair(0, 0.0));
    189   return num * (sum.second / sum.first);
    190 }
    191 
    192 }  // namespace internal
    193 }  // namespace v8
    194