blob: 57dad3db1d9a22409a163d3218794b384180a044 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2012 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.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/counters.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00006
Ben Murdoch097c5b22016-05-18 11:27:45 +01007#include <iomanip>
8
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/base/platform/platform.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/isolate.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040011#include "src/log-inl.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +010012#include "src/log.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000013
14namespace v8 {
15namespace internal {
16
Steve Block44f0eee2011-05-26 01:26:41 +010017StatsTable::StatsTable()
18 : lookup_function_(NULL),
19 create_histogram_function_(NULL),
20 add_histogram_sample_function_(NULL) {}
21
22
23int* StatsCounter::FindLocationInStatsTable() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024 return isolate_->stats_table()->FindLocation(name_);
Steve Block44f0eee2011-05-26 01:26:41 +010025}
26
Steve Blocka7e24c12009-10-30 11:49:00 +000027
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028void Histogram::AddSample(int sample) {
29 if (Enabled()) {
30 isolate()->stats_table()->AddHistogramSample(histogram_, sample);
31 }
Steve Blocka7e24c12009-10-30 11:49:00 +000032}
33
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034void* Histogram::CreateHistogram() const {
35 return isolate()->stats_table()->
36 CreateHistogram(name_, min_, max_, num_buckets_);
Steve Blocka7e24c12009-10-30 11:49:00 +000037}
38
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039
Steve Blocka7e24c12009-10-30 11:49:00 +000040// Start the timer.
41void HistogramTimer::Start() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000042 if (Enabled()) {
43 timer_.Start();
Steve Blocka7e24c12009-10-30 11:49:00 +000044 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040045 Logger::CallEventLogger(isolate(), name(), Logger::START, true);
Steve Blocka7e24c12009-10-30 11:49:00 +000046}
47
Ben Murdochb8a8cc12014-11-26 15:28:44 +000048
Steve Blocka7e24c12009-10-30 11:49:00 +000049// Stop the timer and record the results.
50void HistogramTimer::Stop() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051 if (Enabled()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052 int64_t sample = resolution_ == MICROSECOND
53 ? timer_.Elapsed().InMicroseconds()
54 : timer_.Elapsed().InMilliseconds();
55 // Compute the delta between start and stop, in microseconds.
56 AddSample(static_cast<int>(sample));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057 timer_.Stop();
Steve Blocka7e24c12009-10-30 11:49:00 +000058 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040059 Logger::CallEventLogger(isolate(), name(), Logger::END, true);
Steve Blocka7e24c12009-10-30 11:49:00 +000060}
61
Steve Block44f0eee2011-05-26 01:26:41 +010062
Ben Murdochb8a8cc12014-11-26 15:28:44 +000063Counters::Counters(Isolate* isolate) {
64#define HR(name, caption, min, max, num_buckets) \
65 name##_ = Histogram(#caption, min, max, num_buckets, isolate);
66 HISTOGRAM_RANGE_LIST(HR)
67#undef HR
68
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000069#define HT(name, caption, max, res) \
70 name##_ = HistogramTimer(#caption, 0, max, HistogramTimer::res, 50, isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000071 HISTOGRAM_TIMER_LIST(HT)
72#undef HT
73
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074#define AHT(name, caption) \
75 name##_ = AggregatableHistogramTimer(#caption, 0, 10000000, 50, isolate);
76 AGGREGATABLE_HISTOGRAM_TIMER_LIST(AHT)
77#undef AHT
78
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079#define HP(name, caption) \
80 name##_ = Histogram(#caption, 0, 101, 100, isolate);
81 HISTOGRAM_PERCENTAGE_LIST(HP)
82#undef HP
83
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000084
85// Exponential histogram assigns bucket limits to points
86// p[1], p[2], ... p[n] such that p[i+1] / p[i] = constant.
87// The constant factor is equal to the n-th root of (high / low),
88// where the n is the number of buckets, the low is the lower limit,
89// the high is the upper limit.
90// For n = 50, low = 1000, high = 500000: the factor = 1.13.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091#define HM(name, caption) \
92 name##_ = Histogram(#caption, 1000, 500000, 50, isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000093 HISTOGRAM_LEGACY_MEMORY_LIST(HM)
94#undef HM
95// For n = 100, low = 4000, high = 2000000: the factor = 1.06.
96#define HM(name, caption) \
97 name##_ = Histogram(#caption, 4000, 2000000, 100, isolate);
98 HISTOGRAM_MEMORY_LIST(HM)
99#undef HM
100
101#define HM(name, caption) \
102 aggregated_##name##_ = AggregatedMemoryHistogram<Histogram>(&name##_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000103 HISTOGRAM_MEMORY_LIST(HM)
104#undef HM
105
106#define SC(name, caption) \
107 name##_ = StatsCounter(isolate, "c:" #caption);
108
109 STATS_COUNTER_LIST_1(SC)
110 STATS_COUNTER_LIST_2(SC)
111#undef SC
112
113#define SC(name) \
114 count_of_##name##_ = StatsCounter(isolate, "c:" "V8.CountOf_" #name); \
115 size_of_##name##_ = StatsCounter(isolate, "c:" "V8.SizeOf_" #name);
116 INSTANCE_TYPE_LIST(SC)
117#undef SC
118
119#define SC(name) \
120 count_of_CODE_TYPE_##name##_ = \
121 StatsCounter(isolate, "c:" "V8.CountOf_CODE_TYPE-" #name); \
122 size_of_CODE_TYPE_##name##_ = \
123 StatsCounter(isolate, "c:" "V8.SizeOf_CODE_TYPE-" #name);
124 CODE_KIND_LIST(SC)
125#undef SC
126
127#define SC(name) \
128 count_of_FIXED_ARRAY_##name##_ = \
129 StatsCounter(isolate, "c:" "V8.CountOf_FIXED_ARRAY-" #name); \
130 size_of_FIXED_ARRAY_##name##_ = \
131 StatsCounter(isolate, "c:" "V8.SizeOf_FIXED_ARRAY-" #name);
132 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(SC)
133#undef SC
134
135#define SC(name) \
136 count_of_CODE_AGE_##name##_ = \
137 StatsCounter(isolate, "c:" "V8.CountOf_CODE_AGE-" #name); \
138 size_of_CODE_AGE_##name##_ = \
139 StatsCounter(isolate, "c:" "V8.SizeOf_CODE_AGE-" #name);
140 CODE_AGE_LIST_COMPLETE(SC)
141#undef SC
142}
143
144
145void Counters::ResetCounters() {
146#define SC(name, caption) name##_.Reset();
147 STATS_COUNTER_LIST_1(SC)
148 STATS_COUNTER_LIST_2(SC)
149#undef SC
150
151#define SC(name) \
152 count_of_##name##_.Reset(); \
153 size_of_##name##_.Reset();
154 INSTANCE_TYPE_LIST(SC)
155#undef SC
156
157#define SC(name) \
158 count_of_CODE_TYPE_##name##_.Reset(); \
159 size_of_CODE_TYPE_##name##_.Reset();
160 CODE_KIND_LIST(SC)
161#undef SC
162
163#define SC(name) \
164 count_of_FIXED_ARRAY_##name##_.Reset(); \
165 size_of_FIXED_ARRAY_##name##_.Reset();
166 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(SC)
167#undef SC
168
169#define SC(name) \
170 count_of_CODE_AGE_##name##_.Reset(); \
171 size_of_CODE_AGE_##name##_.Reset();
172 CODE_AGE_LIST_COMPLETE(SC)
173#undef SC
174}
175
176
177void Counters::ResetHistograms() {
178#define HR(name, caption, min, max, num_buckets) name##_.Reset();
179 HISTOGRAM_RANGE_LIST(HR)
180#undef HR
181
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182#define HT(name, caption, max, res) name##_.Reset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 HISTOGRAM_TIMER_LIST(HT)
184#undef HT
185
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186#define AHT(name, caption) name##_.Reset();
187 AGGREGATABLE_HISTOGRAM_TIMER_LIST(AHT)
188#undef AHT
189
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190#define HP(name, caption) name##_.Reset();
191 HISTOGRAM_PERCENTAGE_LIST(HP)
192#undef HP
193
194#define HM(name, caption) name##_.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195 HISTOGRAM_LEGACY_MEMORY_LIST(HM)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196#undef HM
Steve Block44f0eee2011-05-26 01:26:41 +0100197}
198
Ben Murdoch097c5b22016-05-18 11:27:45 +0100199class RuntimeCallStatEntries {
200 public:
201 void Print(std::ostream& os) {
202 if (total_call_count == 0) return;
203 std::sort(entries.rbegin(), entries.rend());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100204 os << std::setw(50) << "Runtime Function/C++ Builtin" << std::setw(12)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100205 << "Time" << std::setw(18) << "Count" << std::endl
Ben Murdoch61f157c2016-09-16 13:49:30 +0100206 << std::string(88, '=') << std::endl;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100207 for (Entry& entry : entries) {
208 entry.SetTotal(total_time, total_call_count);
209 entry.Print(os);
210 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100211 os << std::string(88, '-') << std::endl;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100212 Entry("Total", total_time, total_call_count).Print(os);
213 }
214
215 void Add(RuntimeCallCounter* counter) {
216 if (counter->count == 0) return;
217 entries.push_back(Entry(counter->name, counter->time, counter->count));
218 total_time += counter->time;
219 total_call_count += counter->count;
220 }
221
222 private:
223 class Entry {
224 public:
225 Entry(const char* name, base::TimeDelta time, uint64_t count)
226 : name_(name),
Ben Murdoch61f157c2016-09-16 13:49:30 +0100227 time_(time.InMicroseconds()),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100228 count_(count),
229 time_percent_(100),
230 count_percent_(100) {}
231
232 bool operator<(const Entry& other) const {
233 if (time_ < other.time_) return true;
234 if (time_ > other.time_) return false;
235 return count_ < other.count_;
236 }
237
238 void Print(std::ostream& os) {
239 os.precision(2);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100240 os << std::fixed << std::setprecision(2);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100241 os << std::setw(50) << name_;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100242 os << std::setw(10) << static_cast<double>(time_) / 1000 << "ms ";
Ben Murdoch097c5b22016-05-18 11:27:45 +0100243 os << std::setw(6) << time_percent_ << "%";
244 os << std::setw(10) << count_ << " ";
245 os << std::setw(6) << count_percent_ << "%";
246 os << std::endl;
247 }
248
249 void SetTotal(base::TimeDelta total_time, uint64_t total_count) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100250 if (total_time.InMicroseconds() == 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100251 time_percent_ = 0;
252 } else {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100253 time_percent_ = 100.0 * time_ / total_time.InMicroseconds();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100254 }
255 count_percent_ = 100.0 * count_ / total_count;
256 }
257
258 private:
259 const char* name_;
260 int64_t time_;
261 uint64_t count_;
262 double time_percent_;
263 double count_percent_;
264 };
265
266 uint64_t total_call_count = 0;
267 base::TimeDelta total_time;
268 std::vector<Entry> entries;
269};
270
271void RuntimeCallCounter::Reset() {
272 count = 0;
273 time = base::TimeDelta();
274}
275
Ben Murdochc5610432016-08-08 18:44:38 +0100276// static
277void RuntimeCallStats::Enter(Isolate* isolate, RuntimeCallTimer* timer,
278 CounterId counter_id) {
279 RuntimeCallStats* stats = isolate->counters()->runtime_call_stats();
280 RuntimeCallCounter* counter = &(stats->*counter_id);
281 timer->Start(counter, stats->current_timer_);
282 stats->current_timer_ = timer;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100283}
284
Ben Murdochc5610432016-08-08 18:44:38 +0100285// static
286void RuntimeCallStats::Leave(Isolate* isolate, RuntimeCallTimer* timer) {
287 RuntimeCallStats* stats = isolate->counters()->runtime_call_stats();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100288
289 if (stats->current_timer_ == timer) {
290 stats->current_timer_ = timer->Stop();
291 } else {
292 // Must be a Threading cctest. Walk the chain of Timers to find the
293 // buried one that's leaving. We don't care about keeping nested timings
294 // accurate, just avoid crashing by keeping the chain intact.
295 RuntimeCallTimer* next = stats->current_timer_;
296 while (next->parent_ != timer) next = next->parent_;
297 next->parent_ = timer->Stop();
298 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100299}
300
Ben Murdochc5610432016-08-08 18:44:38 +0100301// static
302void RuntimeCallStats::CorrectCurrentCounterId(Isolate* isolate,
303 CounterId counter_id) {
304 RuntimeCallStats* stats = isolate->counters()->runtime_call_stats();
305 DCHECK_NOT_NULL(stats->current_timer_);
306 RuntimeCallCounter* counter = &(stats->*counter_id);
307 stats->current_timer_->counter_ = counter;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100308}
309
310void RuntimeCallStats::Print(std::ostream& os) {
311 RuntimeCallStatEntries entries;
312
Ben Murdochc5610432016-08-08 18:44:38 +0100313#define PRINT_COUNTER(name) entries.Add(&this->name);
314 FOR_EACH_MANUAL_COUNTER(PRINT_COUNTER)
315#undef PRINT_COUNTER
316
Ben Murdoch097c5b22016-05-18 11:27:45 +0100317#define PRINT_COUNTER(name, nargs, ressize) entries.Add(&this->Runtime_##name);
318 FOR_EACH_INTRINSIC(PRINT_COUNTER)
319#undef PRINT_COUNTER
320
Ben Murdoch61f157c2016-09-16 13:49:30 +0100321#define PRINT_COUNTER(name) entries.Add(&this->Builtin_##name);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100322 BUILTIN_LIST_C(PRINT_COUNTER)
323#undef PRINT_COUNTER
324
Ben Murdochc5610432016-08-08 18:44:38 +0100325#define PRINT_COUNTER(name) entries.Add(&this->API_##name);
326 FOR_EACH_API_COUNTER(PRINT_COUNTER)
327#undef PRINT_COUNTER
328
329#define PRINT_COUNTER(name) entries.Add(&this->Handler_##name);
330 FOR_EACH_HANDLER_COUNTER(PRINT_COUNTER)
331#undef PRINT_COUNTER
Ben Murdoch097c5b22016-05-18 11:27:45 +0100332
333 entries.Print(os);
334}
335
336void RuntimeCallStats::Reset() {
Ben Murdochda12d292016-06-02 14:46:10 +0100337 if (!FLAG_runtime_call_stats) return;
Ben Murdochc5610432016-08-08 18:44:38 +0100338#define RESET_COUNTER(name) this->name.Reset();
339 FOR_EACH_MANUAL_COUNTER(RESET_COUNTER)
340#undef RESET_COUNTER
341
342#define RESET_COUNTER(name, nargs, result_size) this->Runtime_##name.Reset();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100343 FOR_EACH_INTRINSIC(RESET_COUNTER)
344#undef RESET_COUNTER
Ben Murdochc5610432016-08-08 18:44:38 +0100345
Ben Murdoch61f157c2016-09-16 13:49:30 +0100346#define RESET_COUNTER(name) this->Builtin_##name.Reset();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100347 BUILTIN_LIST_C(RESET_COUNTER)
348#undef RESET_COUNTER
Ben Murdoch097c5b22016-05-18 11:27:45 +0100349
Ben Murdochc5610432016-08-08 18:44:38 +0100350#define RESET_COUNTER(name) this->API_##name.Reset();
351 FOR_EACH_API_COUNTER(RESET_COUNTER)
352#undef RESET_COUNTER
Ben Murdoch097c5b22016-05-18 11:27:45 +0100353
Ben Murdochc5610432016-08-08 18:44:38 +0100354#define RESET_COUNTER(name) this->Handler_##name.Reset();
355 FOR_EACH_HANDLER_COUNTER(RESET_COUNTER)
356#undef RESET_COUNTER
Ben Murdoch097c5b22016-05-18 11:27:45 +0100357}
358
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359} // namespace internal
360} // namespace v8