• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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 #ifndef V8_METRICS_H_
6 #define V8_METRICS_H_
7 
8 #include "v8.h"  // NOLINT(build/include_directory)
9 
10 namespace v8 {
11 namespace metrics {
12 
13 // TODO(sartang@microsoft.com): Remove wall_clock_time_in_us.
14 struct WasmModuleDecoded {
15   bool async = false;
16   bool streamed = false;
17   bool success = false;
18   size_t module_size_in_bytes = 0;
19   size_t function_count = 0;
20   int64_t wall_clock_time_in_us = -1;
21   int64_t wall_clock_duration_in_us = -1;
22 };
23 
24 struct WasmModuleCompiled {
25   bool async = false;
26   bool streamed = false;
27   bool cached = false;
28   bool deserialized = false;
29   bool lazy = false;
30   bool success = false;
31   size_t code_size_in_bytes = 0;
32   size_t liftoff_bailout_count = 0;
33   int64_t wall_clock_time_in_us = -1;
34   int64_t wall_clock_duration_in_us = -1;
35 };
36 
37 struct WasmModuleInstantiated {
38   bool async = false;
39   bool success = false;
40   size_t imported_function_count = 0;
41   int64_t wall_clock_time_in_us = -1;
42   int64_t wall_clock_duration_in_us = -1;
43 };
44 
45 struct WasmModuleTieredUp {
46   bool lazy = false;
47   size_t code_size_in_bytes = 0;
48   int64_t wall_clock_time_in_us = -1;
49   int64_t wall_clock_duration_in_us = -1;
50 };
51 
52 struct WasmModulesPerIsolate {
53   size_t count = 0;
54 };
55 
56 #define V8_MAIN_THREAD_METRICS_EVENTS(V) \
57   V(WasmModuleDecoded)                   \
58   V(WasmModuleCompiled)                  \
59   V(WasmModuleInstantiated)              \
60   V(WasmModuleTieredUp)
61 
62 #define V8_THREAD_SAFE_METRICS_EVENTS(V) V(WasmModulesPerIsolate)
63 
64 /**
65  * This class serves as a base class for recording event-based metrics in V8.
66  * There a two kinds of metrics, those which are expected to be thread-safe and
67  * whose implementation is required to fulfill this requirement and those whose
68  * implementation does not have that requirement and only needs to be
69  * executable on the main thread. If such an event is triggered from a
70  * background thread, it will be delayed and executed by the foreground task
71  * runner.
72  *
73  * The thread-safe events are listed in the V8_THREAD_SAFE_METRICS_EVENTS
74  * macro above while the main thread event are listed in
75  * V8_MAIN_THREAD_METRICS_EVENTS above. For the former, a virtual method
76  * AddMainThreadEvent(const E& event, v8::Context::Token token) will be
77  * generated and for the latter AddThreadSafeEvent(const E& event).
78  *
79  * Thread-safe events are not allowed to access the context and therefore do
80  * not carry a context ID with them. These IDs can be generated using
81  * Recorder::GetContextId() and the ID will be valid throughout the lifetime
82  * of the isolate. It is not guaranteed that the ID will still resolve to
83  * a valid context using Recorder::GetContext() at the time the metric is
84  * recorded. In this case, an empty handle will be returned.
85  *
86  * The embedder is expected to call v8::Isolate::SetMetricsRecorder()
87  * providing its implementation and have the virtual methods overwritten
88  * for the events it cares about.
89  */
90 class V8_EXPORT Recorder {
91  public:
92   // A unique identifier for a context in this Isolate.
93   // It is guaranteed to not be reused throughout the lifetime of the Isolate.
94   class ContextId {
95    public:
ContextId()96     ContextId() : id_(kEmptyId) {}
97 
IsEmpty()98     bool IsEmpty() const { return id_ == kEmptyId; }
Empty()99     static const ContextId Empty() { return ContextId{kEmptyId}; }
100 
101     bool operator==(const ContextId& other) const { return id_ == other.id_; }
102     bool operator!=(const ContextId& other) const { return id_ != other.id_; }
103 
104    private:
105     friend class ::v8::Context;
106     friend class ::v8::internal::Isolate;
107 
ContextId(uintptr_t id)108     explicit ContextId(uintptr_t id) : id_(id) {}
109 
110     static constexpr uintptr_t kEmptyId = 0;
111     uintptr_t id_;
112   };
113 
114   virtual ~Recorder() = default;
115 
116 #define ADD_MAIN_THREAD_EVENT(E) \
117   virtual void AddMainThreadEvent(const E& event, ContextId context_id) {}
118   V8_MAIN_THREAD_METRICS_EVENTS(ADD_MAIN_THREAD_EVENT)
119 #undef ADD_MAIN_THREAD_EVENT
120 
121 #define ADD_THREAD_SAFE_EVENT(E) \
122   virtual void AddThreadSafeEvent(const E& event) {}
V8_THREAD_SAFE_METRICS_EVENTS(ADD_THREAD_SAFE_EVENT)123   V8_THREAD_SAFE_METRICS_EVENTS(ADD_THREAD_SAFE_EVENT)
124 #undef ADD_THREAD_SAFE_EVENT
125 
126   virtual void NotifyIsolateDisposal() {}
127 
128   // Return the context with the given id or an empty handle if the context
129   // was already garbage collected.
130   static MaybeLocal<Context> GetContext(Isolate* isolate, ContextId id);
131   // Return the unique id corresponding to the given context.
132   static ContextId GetContextId(Local<Context> context);
133 };
134 
135 }  // namespace metrics
136 }  // namespace v8
137 
138 #endif  // V8_METRICS_H_
139