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::kPrepare: 34 tracer_->RecordPrepare(elapsed); 35 break; 36 case ScopeID::kCompile: 37 tracer_->RecordCompile(elapsed, num_); 38 break; 39 case ScopeID::kFinalize: 40 tracer_->RecordFinalize(elapsed); 41 break; 42 } 43 } 44 45 // static 46 const char* CompilerDispatcherTracer::Scope::Name(ScopeID scope_id) { 47 switch (scope_id) { 48 case ScopeID::kPrepare: 49 return "V8.BackgroundCompile_Prepare"; 50 case ScopeID::kCompile: 51 return "V8.BackgroundCompile_Compile"; 52 case ScopeID::kFinalize: 53 return "V8.BackgroundCompile_Finalize"; 54 } 55 UNREACHABLE(); 56 } 57 58 CompilerDispatcherTracer::CompilerDispatcherTracer(Isolate* isolate) 59 : runtime_call_stats_(nullptr) { 60 // isolate might be nullptr during unittests. 61 if (isolate) { 62 runtime_call_stats_ = isolate->counters()->runtime_call_stats(); 63 } 64 } 65 66 CompilerDispatcherTracer::~CompilerDispatcherTracer() {} 67 68 void CompilerDispatcherTracer::RecordPrepare(double duration_ms) { 69 base::LockGuard<base::Mutex> lock(&mutex_); 70 prepare_events_.Push(duration_ms); 71 } 72 73 void CompilerDispatcherTracer::RecordCompile(double duration_ms, 74 size_t source_length) { 75 base::LockGuard<base::Mutex> lock(&mutex_); 76 compile_events_.Push(std::make_pair(source_length, duration_ms)); 77 } 78 79 void CompilerDispatcherTracer::RecordFinalize(double duration_ms) { 80 base::LockGuard<base::Mutex> lock(&mutex_); 81 finalize_events_.Push(duration_ms); 82 } 83 84 double CompilerDispatcherTracer::EstimatePrepareInMs() const { 85 base::LockGuard<base::Mutex> lock(&mutex_); 86 return Average(prepare_events_); 87 } 88 89 double CompilerDispatcherTracer::EstimateCompileInMs( 90 size_t source_length) const { 91 base::LockGuard<base::Mutex> lock(&mutex_); 92 return Estimate(compile_events_, source_length); 93 } 94 95 double CompilerDispatcherTracer::EstimateFinalizeInMs() const { 96 base::LockGuard<base::Mutex> lock(&mutex_); 97 return Average(finalize_events_); 98 } 99 100 void CompilerDispatcherTracer::DumpStatistics() const { 101 PrintF( 102 "CompilerDispatcherTracer: " 103 "prepare=%.2lfms compiling=%.2lfms/kb finalize=%.2lfms\n", 104 EstimatePrepareInMs(), EstimateCompileInMs(1 * KB), 105 EstimateFinalizeInMs()); 106 } 107 108 double CompilerDispatcherTracer::Average( 109 const base::RingBuffer<double>& buffer) { 110 if (buffer.Count() == 0) return 0.0; 111 double sum = buffer.Sum([](double a, double b) { return a + b; }, 0.0); 112 return sum / buffer.Count(); 113 } 114 115 double CompilerDispatcherTracer::Estimate( 116 const base::RingBuffer<std::pair<size_t, double>>& buffer, size_t num) { 117 if (buffer.Count() == 0) return kEstimatedRuntimeWithoutData; 118 std::pair<size_t, double> sum = buffer.Sum( 119 [](std::pair<size_t, double> a, std::pair<size_t, double> b) { 120 return std::make_pair(a.first + b.first, a.second + b.second); 121 }, 122 std::make_pair(0, 0.0)); 123 return num * (sum.second / sum.first); 124 } 125 126 } // namespace internal 127 } // namespace v8 128