| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_COUNTERS_H_ | 5 #ifndef V8_COUNTERS_H_ |
| 6 #define V8_COUNTERS_H_ | 6 #define V8_COUNTERS_H_ |
| 7 | 7 |
| 8 #include "include/v8.h" | 8 #include "include/v8.h" |
| 9 #include "src/allocation.h" | 9 #include "src/allocation.h" |
| 10 #include "src/base/platform/elapsed-timer.h" | 10 #include "src/base/platform/elapsed-timer.h" |
| 11 #include "src/base/platform/time.h" | 11 #include "src/base/platform/time.h" |
| 12 #include "src/builtins/builtins.h" | 12 #include "src/builtins/builtins.h" |
| 13 #include "src/globals.h" | 13 #include "src/globals.h" |
| 14 #include "src/isolate.h" | |
| 15 #include "src/objects.h" | 14 #include "src/objects.h" |
| 16 #include "src/runtime/runtime.h" | 15 #include "src/runtime/runtime.h" |
| 17 #include "src/tracing/trace-event.h" | |
| 18 | 16 |
| 19 namespace v8 { | 17 namespace v8 { |
| 20 namespace internal { | 18 namespace internal { |
| 21 | 19 |
| 22 // StatsCounters is an interface for plugging into external | 20 // StatsCounters is an interface for plugging into external |
| 23 // counters for monitoring. Counters can be looked up and | 21 // counters for monitoring. Counters can be looked up and |
| 24 // manipulated by name. | 22 // manipulated by name. |
| 25 | 23 |
| 26 class StatsTable { | 24 class StatsTable { |
| 27 public: | 25 public: |
| (...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 765 RuntimeCallCounter API_##name = RuntimeCallCounter("API_" #name); | 763 RuntimeCallCounter API_##name = RuntimeCallCounter("API_" #name); |
| 766 FOR_EACH_API_COUNTER(CALL_BUILTIN_COUNTER) | 764 FOR_EACH_API_COUNTER(CALL_BUILTIN_COUNTER) |
| 767 #undef CALL_BUILTIN_COUNTER | 765 #undef CALL_BUILTIN_COUNTER |
| 768 #define CALL_BUILTIN_COUNTER(name) \ | 766 #define CALL_BUILTIN_COUNTER(name) \ |
| 769 RuntimeCallCounter Handler_##name = RuntimeCallCounter(#name); | 767 RuntimeCallCounter Handler_##name = RuntimeCallCounter(#name); |
| 770 FOR_EACH_HANDLER_COUNTER(CALL_BUILTIN_COUNTER) | 768 FOR_EACH_HANDLER_COUNTER(CALL_BUILTIN_COUNTER) |
| 771 #undef CALL_BUILTIN_COUNTER | 769 #undef CALL_BUILTIN_COUNTER |
| 772 | 770 |
| 773 // Starting measuring the time for a function. This will establish the | 771 // Starting measuring the time for a function. This will establish the |
| 774 // connection to the parent counter for properly calculating the own times. | 772 // connection to the parent counter for properly calculating the own times. |
| 775 static void Enter(RuntimeCallStats* stats, RuntimeCallTimer* timer, | 773 static void Enter(Isolate* isolate, RuntimeCallTimer* timer, |
| 776 CounterId counter_id); | 774 CounterId counter_id); |
| 777 | 775 |
| 778 // Leave a scope for a measured runtime function. This will properly add | 776 // Leave a scope for a measured runtime function. This will properly add |
| 779 // the time delta to the current_counter and subtract the delta from its | 777 // the time delta to the current_counter and subtract the delta from its |
| 780 // parent. | 778 // parent. |
| 781 static void Leave(RuntimeCallStats* stats, RuntimeCallTimer* timer); | 779 static void Leave(Isolate* isolate, RuntimeCallTimer* timer); |
| 782 | 780 |
| 783 // Set counter id for the innermost measurement. It can be used to refine | 781 // Set counter id for the innermost measurement. It can be used to refine |
| 784 // event kind when a runtime entry counter is too generic. | 782 // event kind when a runtime entry counter is too generic. |
| 785 static void CorrectCurrentCounterId(RuntimeCallStats* stats, | 783 static void CorrectCurrentCounterId(Isolate* isolate, CounterId counter_id); |
| 786 CounterId counter_id); | |
| 787 | 784 |
| 788 void Reset(); | 785 void Reset(); |
| 789 V8_NOINLINE void Print(std::ostream& os); | 786 void Print(std::ostream& os); |
| 790 V8_NOINLINE const char* Dump(); | |
| 791 | 787 |
| 792 RuntimeCallStats() { | 788 RuntimeCallStats() { Reset(); } |
| 793 Reset(); | |
| 794 in_use_ = false; | |
| 795 } | |
| 796 | |
| 797 RuntimeCallTimer* current_timer() { return current_timer_; } | 789 RuntimeCallTimer* current_timer() { return current_timer_; } |
| 798 bool InUse() { return in_use_; } | |
| 799 | 790 |
| 800 private: | 791 private: |
| 801 std::stringstream buffer_; | |
| 802 std::unique_ptr<char[]> buffer_c_str_; | |
| 803 size_t len_ = 0; | |
| 804 // Counter to track recursive time events. | 792 // Counter to track recursive time events. |
| 805 RuntimeCallTimer* current_timer_ = NULL; | 793 RuntimeCallTimer* current_timer_ = NULL; |
| 806 bool in_use_; | |
| 807 }; | 794 }; |
| 808 | 795 |
| 809 #define TRACE_RUNTIME_CALL_STATS(isolate, counter_name) \ | 796 #define TRACE_RUNTIME_CALL_STATS(isolate, counter_name) \ |
| 810 do { \ | 797 do { \ |
| 811 if (FLAG_runtime_call_stats) { \ | 798 if (FLAG_runtime_call_stats) { \ |
| 812 RuntimeCallStats::CorrectCurrentCounterId( \ | 799 RuntimeCallStats::CorrectCurrentCounterId( \ |
| 813 isolate->counters()->runtime_call_stats(), \ | 800 isolate, &RuntimeCallStats::counter_name); \ |
| 814 &RuntimeCallStats::counter_name); \ | 801 } \ |
| 815 } \ | |
| 816 if (V8_UNLIKELY(TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_ENABLED())) { \ | |
| 817 RuntimeCallStats::CorrectCurrentCounterId( \ | |
| 818 isolate->counters()->tracing_runtime_call_stats(), \ | |
| 819 &RuntimeCallStats::counter_name); \ | |
| 820 } \ | |
| 821 } while (false) | 802 } while (false) |
| 822 | 803 |
| 823 #define TRACE_HANDLER_STATS(isolate, counter_name) \ | 804 #define TRACE_HANDLER_STATS(isolate, counter_name) \ |
| 824 TRACE_RUNTIME_CALL_STATS(isolate, Handler_##counter_name) | 805 TRACE_RUNTIME_CALL_STATS(isolate, Handler_##counter_name) |
| 825 | 806 |
| 807 // A RuntimeCallTimerScopes wraps around a RuntimeCallTimer to measure the |
| 808 // the time of C++ scope. |
| 809 class RuntimeCallTimerScope { |
| 810 public: |
| 811 inline RuntimeCallTimerScope(Isolate* isolate, |
| 812 RuntimeCallStats::CounterId counter_id) { |
| 813 if (V8_UNLIKELY(FLAG_runtime_call_stats)) { |
| 814 isolate_ = isolate; |
| 815 RuntimeCallStats::Enter(isolate_, &timer_, counter_id); |
| 816 } |
| 817 } |
| 818 // This constructor is here just to avoid calling GetIsolate() when the |
| 819 // stats are disabled and the isolate is not directly available. |
| 820 inline RuntimeCallTimerScope(HeapObject* heap_object, |
| 821 RuntimeCallStats::CounterId counter_id); |
| 822 |
| 823 inline ~RuntimeCallTimerScope() { |
| 824 if (V8_UNLIKELY(FLAG_runtime_call_stats)) { |
| 825 RuntimeCallStats::Leave(isolate_, &timer_); |
| 826 } |
| 827 } |
| 828 |
| 829 private: |
| 830 Isolate* isolate_; |
| 831 RuntimeCallTimer timer_; |
| 832 }; |
| 833 |
| 826 #define HISTOGRAM_RANGE_LIST(HR) \ | 834 #define HISTOGRAM_RANGE_LIST(HR) \ |
| 827 /* Generic range histograms */ \ | 835 /* Generic range histograms */ \ |
| 828 HR(detached_context_age_in_gc, V8.DetachedContextAgeInGC, 0, 20, 21) \ | 836 HR(detached_context_age_in_gc, V8.DetachedContextAgeInGC, 0, 20, 21) \ |
| 829 HR(gc_idle_time_allotted_in_ms, V8.GCIdleTimeAllottedInMS, 0, 10000, 101) \ | 837 HR(gc_idle_time_allotted_in_ms, V8.GCIdleTimeAllottedInMS, 0, 10000, 101) \ |
| 830 HR(gc_idle_time_limit_overshot, V8.GCIdleTimeLimit.Overshot, 0, 10000, 101) \ | 838 HR(gc_idle_time_limit_overshot, V8.GCIdleTimeLimit.Overshot, 0, 10000, 101) \ |
| 831 HR(gc_idle_time_limit_undershot, V8.GCIdleTimeLimit.Undershot, 0, 10000, \ | 839 HR(gc_idle_time_limit_undershot, V8.GCIdleTimeLimit.Undershot, 0, 10000, \ |
| 832 101) \ | 840 101) \ |
| 833 HR(code_cache_reject_reason, V8.CodeCacheRejectReason, 1, 6, 6) \ | 841 HR(code_cache_reject_reason, V8.CodeCacheRejectReason, 1, 6, 6) \ |
| 834 HR(errors_thrown_per_context, V8.ErrorsThrownPerContext, 0, 200, 20) \ | 842 HR(errors_thrown_per_context, V8.ErrorsThrownPerContext, 0, 200, 20) \ |
| 835 HR(debug_feature_usage, V8.DebugFeatureUsage, 1, 7, 7) \ | 843 HR(debug_feature_usage, V8.DebugFeatureUsage, 1, 7, 7) \ |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 #define COUNTER_ID(name) kCountOfCODE_AGE__##name, \ | 1166 #define COUNTER_ID(name) kCountOfCODE_AGE__##name, \ |
| 1159 kSizeOfCODE_AGE__##name, | 1167 kSizeOfCODE_AGE__##name, |
| 1160 CODE_AGE_LIST_COMPLETE(COUNTER_ID) | 1168 CODE_AGE_LIST_COMPLETE(COUNTER_ID) |
| 1161 #undef COUNTER_ID | 1169 #undef COUNTER_ID |
| 1162 stats_counter_count | 1170 stats_counter_count |
| 1163 }; | 1171 }; |
| 1164 | 1172 |
| 1165 void ResetCounters(); | 1173 void ResetCounters(); |
| 1166 void ResetHistograms(); | 1174 void ResetHistograms(); |
| 1167 RuntimeCallStats* runtime_call_stats() { return &runtime_call_stats_; } | 1175 RuntimeCallStats* runtime_call_stats() { return &runtime_call_stats_; } |
| 1168 RuntimeCallStats* tracing_runtime_call_stats() { | |
| 1169 return &tracing_runtime_call_stats_; | |
| 1170 } | |
| 1171 | 1176 |
| 1172 private: | 1177 private: |
| 1173 #define HR(name, caption, min, max, num_buckets) Histogram name##_; | 1178 #define HR(name, caption, min, max, num_buckets) Histogram name##_; |
| 1174 HISTOGRAM_RANGE_LIST(HR) | 1179 HISTOGRAM_RANGE_LIST(HR) |
| 1175 #undef HR | 1180 #undef HR |
| 1176 | 1181 |
| 1177 #define HT(name, caption, max, res) HistogramTimer name##_; | 1182 #define HT(name, caption, max, res) HistogramTimer name##_; |
| 1178 HISTOGRAM_TIMER_LIST(HT) | 1183 HISTOGRAM_TIMER_LIST(HT) |
| 1179 #undef HT | 1184 #undef HT |
| 1180 | 1185 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1223 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(SC) | 1228 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(SC) |
| 1224 #undef SC | 1229 #undef SC |
| 1225 | 1230 |
| 1226 #define SC(name) \ | 1231 #define SC(name) \ |
| 1227 StatsCounter size_of_CODE_AGE_##name##_; \ | 1232 StatsCounter size_of_CODE_AGE_##name##_; \ |
| 1228 StatsCounter count_of_CODE_AGE_##name##_; | 1233 StatsCounter count_of_CODE_AGE_##name##_; |
| 1229 CODE_AGE_LIST_COMPLETE(SC) | 1234 CODE_AGE_LIST_COMPLETE(SC) |
| 1230 #undef SC | 1235 #undef SC |
| 1231 | 1236 |
| 1232 RuntimeCallStats runtime_call_stats_; | 1237 RuntimeCallStats runtime_call_stats_; |
| 1233 RuntimeCallStats tracing_runtime_call_stats_; | |
| 1234 | 1238 |
| 1235 friend class Isolate; | 1239 friend class Isolate; |
| 1236 | 1240 |
| 1237 explicit Counters(Isolate* isolate); | 1241 explicit Counters(Isolate* isolate); |
| 1238 | 1242 |
| 1239 DISALLOW_IMPLICIT_CONSTRUCTORS(Counters); | 1243 DISALLOW_IMPLICIT_CONSTRUCTORS(Counters); |
| 1240 }; | 1244 }; |
| 1241 | 1245 |
| 1242 // A RuntimeCallTimerScopes wraps around a RuntimeCallTimer to measure the | |
| 1243 // the time of C++ scope. | |
| 1244 class RuntimeCallTimerScope { | |
| 1245 public: | |
| 1246 inline RuntimeCallTimerScope(Isolate* isolate, | |
| 1247 RuntimeCallStats::CounterId counter_id) { | |
| 1248 if (V8_UNLIKELY(FLAG_runtime_call_stats)) { | |
| 1249 isolate_ = isolate; | |
| 1250 RuntimeCallStats::Enter(isolate_->counters()->runtime_call_stats(), | |
| 1251 &timer_, counter_id); | |
| 1252 } | |
| 1253 if (V8_UNLIKELY(TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_ENABLED())) { | |
| 1254 isolate_for_tracing_ = isolate; | |
| 1255 RuntimeCallStats::Enter( | |
| 1256 isolate_for_tracing_->counters()->tracing_runtime_call_stats(), | |
| 1257 &trace_event_timer_, counter_id); | |
| 1258 } | |
| 1259 } | |
| 1260 // This constructor is here just to avoid calling GetIsolate() when the | |
| 1261 // stats are disabled and the isolate is not directly available. | |
| 1262 inline RuntimeCallTimerScope(HeapObject* heap_object, | |
| 1263 RuntimeCallStats::CounterId counter_id); | |
| 1264 | |
| 1265 inline ~RuntimeCallTimerScope() { | |
| 1266 if (V8_UNLIKELY(FLAG_runtime_call_stats)) { | |
| 1267 RuntimeCallStats::Leave(isolate_->counters()->runtime_call_stats(), | |
| 1268 &timer_); | |
| 1269 } | |
| 1270 if (V8_UNLIKELY(isolate_for_tracing_ != nullptr)) { | |
| 1271 RuntimeCallStats::Leave( | |
| 1272 isolate_for_tracing_->counters()->tracing_runtime_call_stats(), | |
| 1273 &trace_event_timer_); | |
| 1274 isolate_for_tracing_ = nullptr; | |
| 1275 } | |
| 1276 } | |
| 1277 | |
| 1278 private: | |
| 1279 Isolate* isolate_; | |
| 1280 // TODO(lpy): --runtime-call-stats and tracing should be mutually exclusive | |
| 1281 // with tracing taking precendence. We need to add checks, and use a single | |
| 1282 // isolate reference and a timer for both. | |
| 1283 Isolate* isolate_for_tracing_ = nullptr; | |
| 1284 RuntimeCallTimer timer_; | |
| 1285 RuntimeCallTimer trace_event_timer_; | |
| 1286 }; | |
| 1287 | |
| 1288 } // namespace internal | 1246 } // namespace internal |
| 1289 } // namespace v8 | 1247 } // namespace v8 |
| 1290 | 1248 |
| 1291 #endif // V8_COUNTERS_H_ | 1249 #endif // V8_COUNTERS_H_ |
| OLD | NEW |