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 9 namespace v8 { 10 namespace internal { 11 12 namespace { 13 14 double MonotonicallyIncreasingTimeInMs() { 15 return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() * 16 static_cast<double>(base::Time::kMillisecondsPerSecond); 17 } 18 19 } // namespace 20 21 CompilerDispatcherTracer::Scope::Scope(CompilerDispatcherTracer* tracer, 22 ScopeID scope_id, size_t num) 23 : tracer_(tracer), scope_id_(scope_id), num_(num) { 24 start_time_ = MonotonicallyIncreasingTimeInMs(); 25 // TODO(cbruni): remove once we fully moved to a trace-based system. 26 if (V8_UNLIKELY(FLAG_runtime_stats)) { 27 RuntimeCallStats::Enter(tracer_->runtime_call_stats_, &timer_, 28 &RuntimeCallStats::CompilerDispatcher); 29 } 30 } 31 32 CompilerDispatcherTracer::Scope::~Scope() { 33 double elapsed = MonotonicallyIncreasingTimeInMs() - start_time_; 34 switch (scope_id_) { 35 case ScopeID::kPrepareToParse: 36 tracer_->RecordPrepareToParse(elapsed); 37 break; 38 case ScopeID::kParse: 39 tracer_->RecordParse(elapsed, num_); 40 break; 41 case ScopeID::kFinalizeParsing: 42 tracer_->RecordFinalizeParsing(elapsed); 43 break; 44 case ScopeID::kPrepareToCompile: 45 tracer_->RecordPrepareToCompile(elapsed); 46 break; 47 case ScopeID::kCompile: 48 tracer_->RecordCompile(elapsed, num_); 49 break; 50 case ScopeID::kFinalizeCompiling: 51 tracer_->RecordFinalizeCompiling(elapsed); 52 break; 53 } 54 // TODO(cbruni): remove once we fully moved to a trace-based system. 55 if (V8_UNLIKELY(FLAG_runtime_stats)) { 56 RuntimeCallStats::Leave(tracer_->runtime_call_stats_, &timer_); 57 } 58 } 59 60 // static 61 const char* CompilerDispatcherTracer::Scope::Name(ScopeID scope_id) { 62 switch (scope_id) { 63 case ScopeID::kPrepareToParse: 64 return "V8.BackgroundCompile_PrepareToParse"; 65 case ScopeID::kParse: 66 return "V8.BackgroundCompile_Parse"; 67 case ScopeID::kFinalizeParsing: 68 return "V8.BackgroundCompile_FinalizeParsing"; 69 case ScopeID::kPrepareToCompile: 70 return "V8.BackgroundCompile_PrepareToCompile"; 71 case ScopeID::kCompile: 72 return "V8.BackgroundCompile_Compile"; 73 case ScopeID::kFinalizeCompiling: 74 return "V8.BackgroundCompile_FinalizeCompiling"; 75 } 76 UNREACHABLE(); 77 return nullptr; 78 } 79 80 CompilerDispatcherTracer::CompilerDispatcherTracer(Isolate* isolate) 81 : runtime_call_stats_(nullptr) { 82 // isolate might be nullptr during unittests. 83 if (isolate) { 84 runtime_call_stats_ = isolate->counters()->runtime_call_stats(); 85 } 86 } 87 88 CompilerDispatcherTracer::~CompilerDispatcherTracer() {} 89 90 void CompilerDispatcherTracer::RecordPrepareToParse(double duration_ms) { 91 base::LockGuard<base::Mutex> lock(&mutex_); 92 prepare_parse_events_.Push(duration_ms); 93 } 94 95 void CompilerDispatcherTracer::RecordParse(double duration_ms, 96 size_t source_length) { 97 base::LockGuard<base::Mutex> lock(&mutex_); 98 parse_events_.Push(std::make_pair(source_length, duration_ms)); 99 } 100 101 void CompilerDispatcherTracer::RecordFinalizeParsing(double duration_ms) { 102 base::LockGuard<base::Mutex> lock(&mutex_); 103 finalize_parsing_events_.Push(duration_ms); 104 } 105 106 void CompilerDispatcherTracer::RecordPrepareToCompile(double duration_ms) { 107 base::LockGuard<base::Mutex> lock(&mutex_); 108 prepare_compile_events_.Push(duration_ms); 109 } 110 111 void CompilerDispatcherTracer::RecordCompile(double duration_ms, 112 size_t ast_size_in_bytes) { 113 base::LockGuard<base::Mutex> lock(&mutex_); 114 compile_events_.Push(std::make_pair(ast_size_in_bytes, duration_ms)); 115 } 116 117 void CompilerDispatcherTracer::RecordFinalizeCompiling(double duration_ms) { 118 base::LockGuard<base::Mutex> lock(&mutex_); 119 finalize_compiling_events_.Push(duration_ms); 120 } 121 122 double CompilerDispatcherTracer::EstimatePrepareToParseInMs() const { 123 base::LockGuard<base::Mutex> lock(&mutex_); 124 return Average(prepare_parse_events_); 125 } 126 127 double CompilerDispatcherTracer::EstimateParseInMs(size_t source_length) const { 128 base::LockGuard<base::Mutex> lock(&mutex_); 129 return Estimate(parse_events_, source_length); 130 } 131 132 double CompilerDispatcherTracer::EstimateFinalizeParsingInMs() { 133 base::LockGuard<base::Mutex> lock(&mutex_); 134 return Average(finalize_parsing_events_); 135 } 136 137 double CompilerDispatcherTracer::EstimatePrepareToCompileInMs() { 138 base::LockGuard<base::Mutex> lock(&mutex_); 139 return Average(prepare_compile_events_); 140 } 141 142 double CompilerDispatcherTracer::EstimateCompileInMs(size_t ast_size_in_bytes) { 143 base::LockGuard<base::Mutex> lock(&mutex_); 144 return Estimate(compile_events_, ast_size_in_bytes); 145 } 146 147 double CompilerDispatcherTracer::EstimateFinalizeCompilingInMs() { 148 base::LockGuard<base::Mutex> lock(&mutex_); 149 return Average(finalize_compiling_events_); 150 } 151 152 double CompilerDispatcherTracer::Average( 153 const base::RingBuffer<double>& buffer) { 154 if (buffer.Count() == 0) return 0.0; 155 double sum = buffer.Sum([](double a, double b) { return a + b; }, 0.0); 156 return sum / buffer.Count(); 157 } 158 159 double CompilerDispatcherTracer::Estimate( 160 const base::RingBuffer<std::pair<size_t, double>>& buffer, size_t num) { 161 if (buffer.Count() == 0) return 0.0; 162 std::pair<size_t, double> sum = buffer.Sum( 163 [](std::pair<size_t, double> a, std::pair<size_t, double> b) { 164 return std::make_pair(a.first + b.first, a.second + b.second); 165 }, 166 std::make_pair(0, 0.0)); 167 return num * (sum.second / sum.first); 168 } 169 170 } // namespace internal 171 } // namespace v8 172