• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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