/src/node/src/inspector_profiler.h
Line | Count | Source |
1 | | #ifndef SRC_INSPECTOR_PROFILER_H_ |
2 | | #define SRC_INSPECTOR_PROFILER_H_ |
3 | | |
4 | | #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
5 | | |
6 | | #if !HAVE_INSPECTOR |
7 | | #error("This header can only be used when inspector is enabled") |
8 | | #endif |
9 | | |
10 | | #include <optional> |
11 | | #include <unordered_set> |
12 | | #include "inspector_agent.h" |
13 | | #include "simdjson.h" |
14 | | |
15 | | namespace node { |
16 | | // Forward declaration to break recursive dependency chain with src/env.h. |
17 | | class Environment; |
18 | | |
19 | | namespace profiler { |
20 | | |
21 | | class V8ProfilerConnection { |
22 | | public: |
23 | | class V8ProfilerSessionDelegate : public inspector::InspectorSessionDelegate { |
24 | | public: |
25 | | explicit V8ProfilerSessionDelegate(V8ProfilerConnection* connection) |
26 | 0 | : connection_(connection) {} |
27 | | |
28 | | void SendMessageToFrontend( |
29 | | const v8_inspector::StringView& message) override; |
30 | | |
31 | | private: |
32 | | V8ProfilerConnection* connection_; |
33 | | }; |
34 | | |
35 | | explicit V8ProfilerConnection(Environment* env); |
36 | 0 | virtual ~V8ProfilerConnection() = default; |
37 | | |
38 | 0 | Environment* env() const { return env_; } |
39 | | |
40 | | // Dispatch a protocol message, and returns the id of the message. |
41 | | // `method` does not need to be surrounded by quotes. |
42 | | // The optional `params` should be formatted in JSON. |
43 | | // The strings should be in one byte characters - which is enough for |
44 | | // the commands we use here. |
45 | | uint64_t DispatchMessage(const char* method, |
46 | | const char* params = nullptr, |
47 | | bool is_profile_request = false); |
48 | | |
49 | | // Use DispatchMessage() to dispatch necessary inspector messages |
50 | | // to start and end the profiling. |
51 | | virtual void Start() = 0; |
52 | | virtual void End() = 0; |
53 | | |
54 | | // Return a descriptive name of the profile for debugging. |
55 | | virtual const char* type() const = 0; |
56 | | // Return if the profile is ending and the response can be parsed. |
57 | | virtual bool ending() const = 0; |
58 | | // Return the directory where the profile should be placed. |
59 | | virtual std::string GetDirectory() const = 0; |
60 | | // Return the filename the profile should be written as. |
61 | | virtual std::string GetFilename() const = 0; |
62 | | // Return the profile object parsed from `message.result`, |
63 | | // which will be then written as a JSON. |
64 | | virtual std::optional<std::string_view> GetProfile( |
65 | | simdjson::ondemand::object* result); |
66 | | virtual void WriteProfile(simdjson::ondemand::object* result); |
67 | | |
68 | 0 | bool HasProfileId(uint64_t id) const { return profile_ids_.contains(id); } |
69 | | |
70 | 0 | void RemoveProfileId(uint64_t id) { profile_ids_.erase(id); } |
71 | | |
72 | | private: |
73 | 0 | uint64_t next_id() { return id_++; } |
74 | | std::unique_ptr<inspector::InspectorSession> session_; |
75 | | uint64_t id_ = 1; |
76 | | std::unordered_set<uint64_t> profile_ids_; |
77 | | |
78 | | protected: |
79 | | simdjson::ondemand::parser json_parser_; |
80 | | Environment* env_ = nullptr; |
81 | | }; |
82 | | |
83 | | class V8CoverageConnection : public V8ProfilerConnection { |
84 | | public: |
85 | 0 | explicit V8CoverageConnection(Environment* env) : V8ProfilerConnection(env) {} |
86 | | |
87 | | void Start() override; |
88 | | void End() override; |
89 | | |
90 | 0 | const char* type() const override { return "coverage"; } |
91 | 0 | bool ending() const override { return ending_; } |
92 | | |
93 | | std::string GetDirectory() const override; |
94 | | std::string GetFilename() const override; |
95 | | std::optional<std::string_view> GetProfile( |
96 | | simdjson::ondemand::object* result) override; |
97 | | void WriteProfile(simdjson::ondemand::object* result) override; |
98 | | void WriteSourceMapCache(); |
99 | | void TakeCoverage(); |
100 | | void StopCoverage(); |
101 | | |
102 | | private: |
103 | | std::unique_ptr<inspector::InspectorSession> session_; |
104 | | bool ending_ = false; |
105 | | }; |
106 | | |
107 | | class V8CpuProfilerConnection : public V8ProfilerConnection { |
108 | | public: |
109 | | explicit V8CpuProfilerConnection(Environment* env) |
110 | 0 | : V8ProfilerConnection(env) {} |
111 | | |
112 | | void Start() override; |
113 | | void End() override; |
114 | | |
115 | 0 | const char* type() const override { return "CPU"; } |
116 | 0 | bool ending() const override { return ending_; } |
117 | | |
118 | | std::string GetDirectory() const override; |
119 | | std::string GetFilename() const override; |
120 | | |
121 | | private: |
122 | | std::unique_ptr<inspector::InspectorSession> session_; |
123 | | bool ending_ = false; |
124 | | }; |
125 | | |
126 | | class V8HeapProfilerConnection : public V8ProfilerConnection { |
127 | | public: |
128 | | explicit V8HeapProfilerConnection(Environment* env) |
129 | 0 | : V8ProfilerConnection(env) {} |
130 | | |
131 | | void Start() override; |
132 | | void End() override; |
133 | | |
134 | 0 | const char* type() const override { return "heap"; } |
135 | 0 | bool ending() const override { return ending_; } |
136 | | |
137 | | std::string GetDirectory() const override; |
138 | | std::string GetFilename() const override; |
139 | | |
140 | | private: |
141 | | std::unique_ptr<inspector::InspectorSession> session_; |
142 | | bool ending_ = false; |
143 | | }; |
144 | | |
145 | | } // namespace profiler |
146 | | } // namespace node |
147 | | |
148 | | #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
149 | | #endif // SRC_INSPECTOR_PROFILER_H_ |