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
MonotonicallyIncreasingTimeInMs()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
Scope(CompilerDispatcherTracer * tracer,ScopeID scope_id,size_t num)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
~Scope()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
Name(ScopeID scope_id)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
CompilerDispatcherTracer(Isolate * isolate)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
~CompilerDispatcherTracer()87 CompilerDispatcherTracer::~CompilerDispatcherTracer() {}
88
RecordPrepareToParse(double duration_ms)89 void CompilerDispatcherTracer::RecordPrepareToParse(double duration_ms) {
90 base::LockGuard<base::Mutex> lock(&mutex_);
91 prepare_parse_events_.Push(duration_ms);
92 }
93
RecordParse(double duration_ms,size_t source_length)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
RecordFinalizeParsing(double duration_ms)100 void CompilerDispatcherTracer::RecordFinalizeParsing(double duration_ms) {
101 base::LockGuard<base::Mutex> lock(&mutex_);
102 finalize_parsing_events_.Push(duration_ms);
103 }
104
RecordAnalyze(double duration_ms)105 void CompilerDispatcherTracer::RecordAnalyze(double duration_ms) {
106 base::LockGuard<base::Mutex> lock(&mutex_);
107 analyze_events_.Push(duration_ms);
108 }
109
RecordPrepareToCompile(double duration_ms)110 void CompilerDispatcherTracer::RecordPrepareToCompile(double duration_ms) {
111 base::LockGuard<base::Mutex> lock(&mutex_);
112 prepare_compile_events_.Push(duration_ms);
113 }
114
RecordCompile(double duration_ms,size_t ast_size_in_bytes)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
RecordFinalizeCompiling(double duration_ms)121 void CompilerDispatcherTracer::RecordFinalizeCompiling(double duration_ms) {
122 base::LockGuard<base::Mutex> lock(&mutex_);
123 finalize_compiling_events_.Push(duration_ms);
124 }
125
EstimatePrepareToParseInMs() const126 double CompilerDispatcherTracer::EstimatePrepareToParseInMs() const {
127 base::LockGuard<base::Mutex> lock(&mutex_);
128 return Average(prepare_parse_events_);
129 }
130
EstimateParseInMs(size_t source_length) const131 double CompilerDispatcherTracer::EstimateParseInMs(size_t source_length) const {
132 base::LockGuard<base::Mutex> lock(&mutex_);
133 return Estimate(parse_events_, source_length);
134 }
135
EstimateFinalizeParsingInMs() const136 double CompilerDispatcherTracer::EstimateFinalizeParsingInMs() const {
137 base::LockGuard<base::Mutex> lock(&mutex_);
138 return Average(finalize_parsing_events_);
139 }
140
EstimateAnalyzeInMs() const141 double CompilerDispatcherTracer::EstimateAnalyzeInMs() const {
142 base::LockGuard<base::Mutex> lock(&mutex_);
143 return Average(analyze_events_);
144 }
145
EstimatePrepareToCompileInMs() const146 double CompilerDispatcherTracer::EstimatePrepareToCompileInMs() const {
147 base::LockGuard<base::Mutex> lock(&mutex_);
148 return Average(prepare_compile_events_);
149 }
150
EstimateCompileInMs(size_t ast_size_in_bytes) const151 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
EstimateFinalizeCompilingInMs() const157 double CompilerDispatcherTracer::EstimateFinalizeCompilingInMs() const {
158 base::LockGuard<base::Mutex> lock(&mutex_);
159 return Average(finalize_compiling_events_);
160 }
161
DumpStatistics() const162 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
Average(const base::RingBuffer<double> & buffer)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
Estimate(const base::RingBuffer<std::pair<size_t,double>> & buffer,size_t num)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