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
MonotonicallyIncreasingTimeInMs()14 double MonotonicallyIncreasingTimeInMs() {
15 return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() *
16 static_cast<double>(base::Time::kMillisecondsPerSecond);
17 }
18
19 } // namespace
20
Scope(CompilerDispatcherTracer * tracer,ScopeID scope_id,size_t num)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
~Scope()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
Name(ScopeID scope_id)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
CompilerDispatcherTracer(Isolate * isolate)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
~CompilerDispatcherTracer()88 CompilerDispatcherTracer::~CompilerDispatcherTracer() {}
89
RecordPrepareToParse(double duration_ms)90 void CompilerDispatcherTracer::RecordPrepareToParse(double duration_ms) {
91 base::LockGuard<base::Mutex> lock(&mutex_);
92 prepare_parse_events_.Push(duration_ms);
93 }
94
RecordParse(double duration_ms,size_t source_length)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
RecordFinalizeParsing(double duration_ms)101 void CompilerDispatcherTracer::RecordFinalizeParsing(double duration_ms) {
102 base::LockGuard<base::Mutex> lock(&mutex_);
103 finalize_parsing_events_.Push(duration_ms);
104 }
105
RecordPrepareToCompile(double duration_ms)106 void CompilerDispatcherTracer::RecordPrepareToCompile(double duration_ms) {
107 base::LockGuard<base::Mutex> lock(&mutex_);
108 prepare_compile_events_.Push(duration_ms);
109 }
110
RecordCompile(double duration_ms,size_t ast_size_in_bytes)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
RecordFinalizeCompiling(double duration_ms)117 void CompilerDispatcherTracer::RecordFinalizeCompiling(double duration_ms) {
118 base::LockGuard<base::Mutex> lock(&mutex_);
119 finalize_compiling_events_.Push(duration_ms);
120 }
121
EstimatePrepareToParseInMs() const122 double CompilerDispatcherTracer::EstimatePrepareToParseInMs() const {
123 base::LockGuard<base::Mutex> lock(&mutex_);
124 return Average(prepare_parse_events_);
125 }
126
EstimateParseInMs(size_t source_length) const127 double CompilerDispatcherTracer::EstimateParseInMs(size_t source_length) const {
128 base::LockGuard<base::Mutex> lock(&mutex_);
129 return Estimate(parse_events_, source_length);
130 }
131
EstimateFinalizeParsingInMs()132 double CompilerDispatcherTracer::EstimateFinalizeParsingInMs() {
133 base::LockGuard<base::Mutex> lock(&mutex_);
134 return Average(finalize_parsing_events_);
135 }
136
EstimatePrepareToCompileInMs()137 double CompilerDispatcherTracer::EstimatePrepareToCompileInMs() {
138 base::LockGuard<base::Mutex> lock(&mutex_);
139 return Average(prepare_compile_events_);
140 }
141
EstimateCompileInMs(size_t ast_size_in_bytes)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
EstimateFinalizeCompilingInMs()147 double CompilerDispatcherTracer::EstimateFinalizeCompilingInMs() {
148 base::LockGuard<base::Mutex> lock(&mutex_);
149 return Average(finalize_compiling_events_);
150 }
151
Average(const base::RingBuffer<double> & buffer)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
Estimate(const base::RingBuffer<std::pair<size_t,double>> & buffer,size_t num)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