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