Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1 | // 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 Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 4 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 5 | #include "src/counters.h" |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 6 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame^] | 7 | #include <iomanip> |
| 8 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 9 | #include "src/base/platform/platform.h" |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 10 | #include "src/isolate.h" |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 11 | #include "src/log-inl.h" |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 12 | |
| 13 | namespace v8 { |
| 14 | namespace internal { |
| 15 | |
Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 16 | StatsTable::StatsTable() |
| 17 | : lookup_function_(NULL), |
| 18 | create_histogram_function_(NULL), |
| 19 | add_histogram_sample_function_(NULL) {} |
| 20 | |
| 21 | |
| 22 | int* StatsCounter::FindLocationInStatsTable() const { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 23 | return isolate_->stats_table()->FindLocation(name_); |
Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 24 | } |
| 25 | |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 26 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 27 | void Histogram::AddSample(int sample) { |
| 28 | if (Enabled()) { |
| 29 | isolate()->stats_table()->AddHistogramSample(histogram_, sample); |
| 30 | } |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 31 | } |
| 32 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 33 | void* Histogram::CreateHistogram() const { |
| 34 | return isolate()->stats_table()-> |
| 35 | CreateHistogram(name_, min_, max_, num_buckets_); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 36 | } |
| 37 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 38 | |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 39 | // Start the timer. |
| 40 | void HistogramTimer::Start() { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 41 | if (Enabled()) { |
| 42 | timer_.Start(); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 43 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 44 | Logger::CallEventLogger(isolate(), name(), Logger::START, true); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 45 | } |
| 46 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 47 | |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 48 | // Stop the timer and record the results. |
| 49 | void HistogramTimer::Stop() { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 50 | if (Enabled()) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 51 | 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 Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 56 | timer_.Stop(); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 57 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 58 | Logger::CallEventLogger(isolate(), name(), Logger::END, true); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 59 | } |
| 60 | |
Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 61 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 62 | Counters::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 Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 68 | #define HT(name, caption, max, res) \ |
| 69 | name##_ = HistogramTimer(#caption, 0, max, HistogramTimer::res, 50, isolate); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 70 | HISTOGRAM_TIMER_LIST(HT) |
| 71 | #undef HT |
| 72 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 73 | #define AHT(name, caption) \ |
| 74 | name##_ = AggregatableHistogramTimer(#caption, 0, 10000000, 50, isolate); |
| 75 | AGGREGATABLE_HISTOGRAM_TIMER_LIST(AHT) |
| 76 | #undef AHT |
| 77 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 78 | #define HP(name, caption) \ |
| 79 | name##_ = Histogram(#caption, 0, 101, 100, isolate); |
| 80 | HISTOGRAM_PERCENTAGE_LIST(HP) |
| 81 | #undef HP |
| 82 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 83 | |
| 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 Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 90 | #define HM(name, caption) \ |
| 91 | name##_ = Histogram(#caption, 1000, 500000, 50, isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 92 | 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 Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 102 | 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 | |
| 144 | void 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 | |
| 176 | void Counters::ResetHistograms() { |
| 177 | #define HR(name, caption, min, max, num_buckets) name##_.Reset(); |
| 178 | HISTOGRAM_RANGE_LIST(HR) |
| 179 | #undef HR |
| 180 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 181 | #define HT(name, caption, max, res) name##_.Reset(); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 182 | HISTOGRAM_TIMER_LIST(HT) |
| 183 | #undef HT |
| 184 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 185 | #define AHT(name, caption) name##_.Reset(); |
| 186 | AGGREGATABLE_HISTOGRAM_TIMER_LIST(AHT) |
| 187 | #undef AHT |
| 188 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 189 | #define HP(name, caption) name##_.Reset(); |
| 190 | HISTOGRAM_PERCENTAGE_LIST(HP) |
| 191 | #undef HP |
| 192 | |
| 193 | #define HM(name, caption) name##_.Reset(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 194 | HISTOGRAM_LEGACY_MEMORY_LIST(HM) |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 195 | #undef HM |
Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 196 | } |
| 197 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame^] | 198 | class 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 | |
| 270 | void RuntimeCallCounter::Reset() { |
| 271 | count = 0; |
| 272 | time = base::TimeDelta(); |
| 273 | } |
| 274 | |
| 275 | void RuntimeCallStats::Enter(RuntimeCallCounter* counter) { |
| 276 | Enter(new RuntimeCallTimer(counter, current_timer_)); |
| 277 | } |
| 278 | |
| 279 | void RuntimeCallStats::Enter(RuntimeCallTimer* timer_) { |
| 280 | current_timer_ = timer_; |
| 281 | current_timer_->Start(); |
| 282 | } |
| 283 | |
| 284 | void RuntimeCallStats::Leave() { |
| 285 | RuntimeCallTimer* timer = current_timer_; |
| 286 | Leave(timer); |
| 287 | delete timer; |
| 288 | } |
| 289 | |
| 290 | void RuntimeCallStats::Leave(RuntimeCallTimer* timer) { |
| 291 | current_timer_ = timer->Stop(); |
| 292 | } |
| 293 | |
| 294 | void 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 | |
| 311 | void 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 | |
| 320 | RuntimeCallTimerScope::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 | |
| 329 | RuntimeCallTimerScope::~RuntimeCallTimerScope() { |
| 330 | if (!FLAG_runtime_call_stats) return; |
| 331 | isolate_->counters()->runtime_call_stats()->Leave(&timer_); |
| 332 | } |
| 333 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 334 | } // namespace internal |
| 335 | } // namespace v8 |