blob: a10494e1658772b82de18fae9333e49038406a7a [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"
Steve Blocka7e24c12009-10-30 11:49:00 +000012
13namespace v8 {
14namespace internal {
15
Steve Block44f0eee2011-05-26 01:26:41 +010016StatsTable::StatsTable()
17 : lookup_function_(NULL),
18 create_histogram_function_(NULL),
19 add_histogram_sample_function_(NULL) {}
20
21
22int* StatsCounter::FindLocationInStatsTable() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023 return isolate_->stats_table()->FindLocation(name_);
Steve Block44f0eee2011-05-26 01:26:41 +010024}
25
Steve Blocka7e24c12009-10-30 11:49:00 +000026
Ben Murdochb8a8cc12014-11-26 15:28:44 +000027void Histogram::AddSample(int sample) {
28 if (Enabled()) {
29 isolate()->stats_table()->AddHistogramSample(histogram_, sample);
30 }
Steve Blocka7e24c12009-10-30 11:49:00 +000031}
32
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033void* Histogram::CreateHistogram() const {
34 return isolate()->stats_table()->
35 CreateHistogram(name_, min_, max_, num_buckets_);
Steve Blocka7e24c12009-10-30 11:49:00 +000036}
37
Ben Murdochb8a8cc12014-11-26 15:28:44 +000038
Steve Blocka7e24c12009-10-30 11:49:00 +000039// Start the timer.
40void HistogramTimer::Start() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041 if (Enabled()) {
42 timer_.Start();
Steve Blocka7e24c12009-10-30 11:49:00 +000043 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040044 Logger::CallEventLogger(isolate(), name(), Logger::START, true);
Steve Blocka7e24c12009-10-30 11:49:00 +000045}
46
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047
Steve Blocka7e24c12009-10-30 11:49:00 +000048// Stop the timer and record the results.
49void HistogramTimer::Stop() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050 if (Enabled()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051 int64_t sample = resolution_ == MICROSECOND
52 ? timer_.Elapsed().InMicroseconds()
53 : timer_.Elapsed().InMilliseconds();
54 // Compute the delta between start and stop, in microseconds.
55 AddSample(static_cast<int>(sample));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000056 timer_.Stop();
Steve Blocka7e24c12009-10-30 11:49:00 +000057 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040058 Logger::CallEventLogger(isolate(), name(), Logger::END, true);
Steve Blocka7e24c12009-10-30 11:49:00 +000059}
60
Steve Block44f0eee2011-05-26 01:26:41 +010061
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062Counters::Counters(Isolate* isolate) {
63#define HR(name, caption, min, max, num_buckets) \
64 name##_ = Histogram(#caption, min, max, num_buckets, isolate);
65 HISTOGRAM_RANGE_LIST(HR)
66#undef HR
67
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068#define HT(name, caption, max, res) \
69 name##_ = HistogramTimer(#caption, 0, max, HistogramTimer::res, 50, isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000070 HISTOGRAM_TIMER_LIST(HT)
71#undef HT
72
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073#define AHT(name, caption) \
74 name##_ = AggregatableHistogramTimer(#caption, 0, 10000000, 50, isolate);
75 AGGREGATABLE_HISTOGRAM_TIMER_LIST(AHT)
76#undef AHT
77
Ben Murdochb8a8cc12014-11-26 15:28:44 +000078#define HP(name, caption) \
79 name##_ = Histogram(#caption, 0, 101, 100, isolate);
80 HISTOGRAM_PERCENTAGE_LIST(HP)
81#undef HP
82
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083
84// Exponential histogram assigns bucket limits to points
85// p[1], p[2], ... p[n] such that p[i+1] / p[i] = constant.
86// The constant factor is equal to the n-th root of (high / low),
87// where the n is the number of buckets, the low is the lower limit,
88// the high is the upper limit.
89// For n = 50, low = 1000, high = 500000: the factor = 1.13.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000090#define HM(name, caption) \
91 name##_ = Histogram(#caption, 1000, 500000, 50, isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000092 HISTOGRAM_LEGACY_MEMORY_LIST(HM)
93#undef HM
94// For n = 100, low = 4000, high = 2000000: the factor = 1.06.
95#define HM(name, caption) \
96 name##_ = Histogram(#caption, 4000, 2000000, 100, isolate);
97 HISTOGRAM_MEMORY_LIST(HM)
98#undef HM
99
100#define HM(name, caption) \
101 aggregated_##name##_ = AggregatedMemoryHistogram<Histogram>(&name##_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000102 HISTOGRAM_MEMORY_LIST(HM)
103#undef HM
104
105#define SC(name, caption) \
106 name##_ = StatsCounter(isolate, "c:" #caption);
107
108 STATS_COUNTER_LIST_1(SC)
109 STATS_COUNTER_LIST_2(SC)
110#undef SC
111
112#define SC(name) \
113 count_of_##name##_ = StatsCounter(isolate, "c:" "V8.CountOf_" #name); \
114 size_of_##name##_ = StatsCounter(isolate, "c:" "V8.SizeOf_" #name);
115 INSTANCE_TYPE_LIST(SC)
116#undef SC
117
118#define SC(name) \
119 count_of_CODE_TYPE_##name##_ = \
120 StatsCounter(isolate, "c:" "V8.CountOf_CODE_TYPE-" #name); \
121 size_of_CODE_TYPE_##name##_ = \
122 StatsCounter(isolate, "c:" "V8.SizeOf_CODE_TYPE-" #name);
123 CODE_KIND_LIST(SC)
124#undef SC
125
126#define SC(name) \
127 count_of_FIXED_ARRAY_##name##_ = \
128 StatsCounter(isolate, "c:" "V8.CountOf_FIXED_ARRAY-" #name); \
129 size_of_FIXED_ARRAY_##name##_ = \
130 StatsCounter(isolate, "c:" "V8.SizeOf_FIXED_ARRAY-" #name);
131 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(SC)
132#undef SC
133
134#define SC(name) \
135 count_of_CODE_AGE_##name##_ = \
136 StatsCounter(isolate, "c:" "V8.CountOf_CODE_AGE-" #name); \
137 size_of_CODE_AGE_##name##_ = \
138 StatsCounter(isolate, "c:" "V8.SizeOf_CODE_AGE-" #name);
139 CODE_AGE_LIST_COMPLETE(SC)
140#undef SC
141}
142
143
144void Counters::ResetCounters() {
145#define SC(name, caption) name##_.Reset();
146 STATS_COUNTER_LIST_1(SC)
147 STATS_COUNTER_LIST_2(SC)
148#undef SC
149
150#define SC(name) \
151 count_of_##name##_.Reset(); \
152 size_of_##name##_.Reset();
153 INSTANCE_TYPE_LIST(SC)
154#undef SC
155
156#define SC(name) \
157 count_of_CODE_TYPE_##name##_.Reset(); \
158 size_of_CODE_TYPE_##name##_.Reset();
159 CODE_KIND_LIST(SC)
160#undef SC
161
162#define SC(name) \
163 count_of_FIXED_ARRAY_##name##_.Reset(); \
164 size_of_FIXED_ARRAY_##name##_.Reset();
165 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(SC)
166#undef SC
167
168#define SC(name) \
169 count_of_CODE_AGE_##name##_.Reset(); \
170 size_of_CODE_AGE_##name##_.Reset();
171 CODE_AGE_LIST_COMPLETE(SC)
172#undef SC
173}
174
175
176void Counters::ResetHistograms() {
177#define HR(name, caption, min, max, num_buckets) name##_.Reset();
178 HISTOGRAM_RANGE_LIST(HR)
179#undef HR
180
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181#define HT(name, caption, max, res) name##_.Reset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000182 HISTOGRAM_TIMER_LIST(HT)
183#undef HT
184
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000185#define AHT(name, caption) name##_.Reset();
186 AGGREGATABLE_HISTOGRAM_TIMER_LIST(AHT)
187#undef AHT
188
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189#define HP(name, caption) name##_.Reset();
190 HISTOGRAM_PERCENTAGE_LIST(HP)
191#undef HP
192
193#define HM(name, caption) name##_.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000194 HISTOGRAM_LEGACY_MEMORY_LIST(HM)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000195#undef HM
Steve Block44f0eee2011-05-26 01:26:41 +0100196}
197
Ben Murdoch097c5b22016-05-18 11:27:45 +0100198class RuntimeCallStatEntries {
199 public:
200 void Print(std::ostream& os) {
201 if (total_call_count == 0) return;
202 std::sort(entries.rbegin(), entries.rend());
203 os << std::setw(50) << "Runtime Function/C++ Builtin" << std::setw(10)
204 << "Time" << std::setw(18) << "Count" << std::endl
205 << std::string(86, '=') << std::endl;
206 for (Entry& entry : entries) {
207 entry.SetTotal(total_time, total_call_count);
208 entry.Print(os);
209 }
210 os << std::string(86, '-') << std::endl;
211 Entry("Total", total_time, total_call_count).Print(os);
212 }
213
214 void Add(RuntimeCallCounter* counter) {
215 if (counter->count == 0) return;
216 entries.push_back(Entry(counter->name, counter->time, counter->count));
217 total_time += counter->time;
218 total_call_count += counter->count;
219 }
220
221 private:
222 class Entry {
223 public:
224 Entry(const char* name, base::TimeDelta time, uint64_t count)
225 : name_(name),
226 time_(time.InMilliseconds()),
227 count_(count),
228 time_percent_(100),
229 count_percent_(100) {}
230
231 bool operator<(const Entry& other) const {
232 if (time_ < other.time_) return true;
233 if (time_ > other.time_) return false;
234 return count_ < other.count_;
235 }
236
237 void Print(std::ostream& os) {
238 os.precision(2);
239 os << std::fixed;
240 os << std::setw(50) << name_;
241 os << std::setw(8) << time_ << "ms ";
242 os << std::setw(6) << time_percent_ << "%";
243 os << std::setw(10) << count_ << " ";
244 os << std::setw(6) << count_percent_ << "%";
245 os << std::endl;
246 }
247
248 void SetTotal(base::TimeDelta total_time, uint64_t total_count) {
249 if (total_time.InMilliseconds() == 0) {
250 time_percent_ = 0;
251 } else {
252 time_percent_ = 100.0 * time_ / total_time.InMilliseconds();
253 }
254 count_percent_ = 100.0 * count_ / total_count;
255 }
256
257 private:
258 const char* name_;
259 int64_t time_;
260 uint64_t count_;
261 double time_percent_;
262 double count_percent_;
263 };
264
265 uint64_t total_call_count = 0;
266 base::TimeDelta total_time;
267 std::vector<Entry> entries;
268};
269
270void RuntimeCallCounter::Reset() {
271 count = 0;
272 time = base::TimeDelta();
273}
274
275void RuntimeCallStats::Enter(RuntimeCallCounter* counter) {
276 Enter(new RuntimeCallTimer(counter, current_timer_));
277}
278
279void RuntimeCallStats::Enter(RuntimeCallTimer* timer_) {
280 current_timer_ = timer_;
281 current_timer_->Start();
282}
283
284void RuntimeCallStats::Leave() {
285 RuntimeCallTimer* timer = current_timer_;
286 Leave(timer);
287 delete timer;
288}
289
290void RuntimeCallStats::Leave(RuntimeCallTimer* timer) {
291 current_timer_ = timer->Stop();
292}
293
294void RuntimeCallStats::Print(std::ostream& os) {
295 RuntimeCallStatEntries entries;
296
297#define PRINT_COUNTER(name, nargs, ressize) entries.Add(&this->Runtime_##name);
298 FOR_EACH_INTRINSIC(PRINT_COUNTER)
299#undef PRINT_COUNTER
300
301#define PRINT_COUNTER(name, type) entries.Add(&this->Builtin_##name);
302 BUILTIN_LIST_C(PRINT_COUNTER)
303#undef PRINT_COUNTER
304
305 entries.Add(&this->ExternalCallback);
306 entries.Add(&this->UnexpectedStubMiss);
307
308 entries.Print(os);
309}
310
311void RuntimeCallStats::Reset() {
312#define RESET_COUNTER(name, nargs, ressize) this->Runtime_##name.Reset();
313 FOR_EACH_INTRINSIC(RESET_COUNTER)
314#undef RESET_COUNTER
315#define RESET_COUNTER(name, type) this->Builtin_##name.Reset();
316 BUILTIN_LIST_C(RESET_COUNTER)
317#undef RESET_COUNTER
318}
319
320RuntimeCallTimerScope::RuntimeCallTimerScope(Isolate* isolate,
321 RuntimeCallCounter* counter)
322 : isolate_(isolate),
323 timer_(counter,
324 isolate->counters()->runtime_call_stats()->current_timer()) {
325 if (!FLAG_runtime_call_stats) return;
326 isolate->counters()->runtime_call_stats()->Enter(&timer_);
327}
328
329RuntimeCallTimerScope::~RuntimeCallTimerScope() {
330 if (!FLAG_runtime_call_stats) return;
331 isolate_->counters()->runtime_call_stats()->Leave(&timer_);
332}
333
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334} // namespace internal
335} // namespace v8