8000 src: refactor V8ProfilerConnection to be more reusable · nodejs/node@0c9bc02 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Commit 0c9bc02

Browse files
joyeecheungtargos
authored andcommitted
src: refactor V8ProfilerConnection to be more reusable
Now the subclasses only need to override methods to - Get the profile node from the profiler response message object - Return the directory and file path And the V8ProfilerConnection() would handle the rest of profile serialization and message parsing. This makes it easier to add other types of profiles in the future. PR-URL: #27475 Refs: #27421 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
1 parent c787bb8 commit 0c9bc02

File tree

2 files changed

+141
-142
lines changed

2 files changed

+141
-142
lines changed

src/inspector_profiler.cc

+109-125
10000
Original file line numberDiff line numberDiff line change
@@ -50,58 +50,71 @@ void V8ProfilerConnection::DispatchMessage(Local<String> message) {
5050
session_->Dispatch(ToProtocolString(env()->isolate(), message)->string());
5151
}
5252

53-
bool V8ProfilerConnection::WriteResult(const char* path, Local<String> result) {
54-
int ret = WriteFileSync(env()->isolate(), path, result);
53+
static void WriteResult(Environment* env,
54+
const char* path,
55+
Local<String> result) {
56+
int ret = WriteFileSync(env->isolate(), path, result);
5557
if (ret != 0) {
5658
char err_buf[128< 8000 /span>];
5759
uv_err_name_r(ret, err_buf, sizeof(err_buf));
5860
fprintf(stderr, "%s: Failed to write file %s\n", err_buf, path);
59-
return false;
61+
return;
6062
}
61-
Debug(
62-
env(), DebugCategory::INSPECTOR_PROFILER, "Written result to %s\n", path);
63-
return true;
63+
Debug(env, DebugCategory::INSPECTOR_PROFILER, "Written result to %s\n", path);
6464
}
6565

66-
void V8CoverageConnection::OnMessage(const v8_inspector::StringView& message) {
67-
Debug(env(),
66+
void V8ProfilerConnection::V8ProfilerSessionDelegate::SendMessageToFrontend(
67+
const v8_inspector::StringView& message) {
68+
Environment* env = connection_->env();
69+
Isolate* isolate = env->isolate();
70+
HandleScope handle_scope(isolate);
71+
Context::Scope context_scope(env->context());
72+
73+
// TODO(joyeecheung): always parse the message so that we can use the id to
74+
// identify ending messages as well as printing the message in the debug
75+
// output when there is an error.
76+
const char* type = connection_->type();
77+
Debug(env,
6878
DebugCategory::INSPECTOR_PROFILER,
69-
"Receive coverage message, ending = %s\n",
70-
ending_ ? "true" : "false");
71-
if (!ending_) {
79+
"Receive %s profile message, ending = %s\n",
80+
type,
81+
connection_->ending() ? "true" : "false");
82+
if (!connection_->ending()) {
7283
return;
7384
}
74-
Isolate* isolate = env()->isolate();
75-
Local<Context> context = env()->context();
76-
HandleScope handle_scope(isolate);
77-
Context::Scope context_scope(context);
78-
Local<String> result;
85+
86+
// Convert StringView to a Local<String>.
87+
Local<String> message_str;
7988
if (!String::NewFromTwoByte(isolate,
8089
message.characters16(),
8190
NewStringType::kNormal,
8291
message.length())
83-
.ToLocal(&result)) {
84-
fprintf(stderr, "Failed to covert coverage message\n");
92+
.ToLocal(&message_str)) {
93+
fprintf(stderr, "Failed to covert %s profile message\n", type);
94+
return;
8595
}
86-
WriteCoverage(result);
96+
97+
connection_->WriteProfile(message_str);
8798
}
8899

89-
bool V8CoverageConnection::WriteCoverage(Local<String> message) {
90-
const std::string& directory = env()->coverage_directory();
91-
CHECK(!directory.empty());
100+
static bool EnsureDirectory(const std::string& directory, const char* type) {
92101
uv_fs_t req;
93102
int ret = fs::MKDirpSync(nullptr, &req, directory, 0777, nullptr);
94103
uv_fs_req_cleanup(&req);
95104
if (ret < 0 && ret != UV_EEXIST) {
96105
char err_buf[128];
97106
uv_err_name_r(ret, err_buf, sizeof(err_buf));
98107
fprintf(stderr,
99-
"%s: Failed to create coverage directory %s\n",
108+
"%s: Failed to create %s profile directory %s\n",
100109
err_buf,
110+
type,
101111
directory.c_str());
102112
return false;
103113
}
114+
return true;
115+
}
104116

117+
std::string V8CoverageConnection::GetFilename() const {
105118
std::string thread_id = std::to_string(env()->thread_id());
106119
std::string pid = std::to_string(uv_os_getpid());
107120
std::string timestamp = std::to_string(
@@ -113,44 +126,79 @@ bool V8CoverageConnection::WriteCoverage(Local<String> message) {
113126
pid.c_str(),
114127
timestamp.c_str(),
115128
thread_id.c_str());
116-
std::string target = directory + kPathSeparator + filename;
117-
MaybeLocal<String> result = GetResult(message);
118-
if (result.IsEmpty()) {
119-
return false;
120-
}
121-
return WriteResult(target.c_str(), result.ToLocalChecked());
129+
return filename;
122130
}
123131

124-
MaybeLocal<String> V8CoverageConnection::GetResult(Local<String> message) {
125-
Local<Context> context = env()->context();
126-
Isolate* isolate = env()->isolate();
132+
static MaybeLocal<Object> ParseProfile(Environment* env,
133+
Local<String> message,
134+
const char* type) {
135+
Local<Context> context = env->context();
136+
Isolate* isolate = env->isolate();
137+
138+
// Get message.result from the response
127139
Local<Value> parsed;
128140
if (!v8::JSON::Parse(context, message).ToLocal(&parsed) ||
129141
!parsed->IsObject()) {
130-
fprintf(stderr, "Failed to parse coverage result as JSON object\n");
131-
return MaybeLocal<String>();
142+
fprintf(stderr, "Failed to parse %s profile result as JSON object\n", type);
143+
return MaybeLocal<Object>();
132144
}
133145

134146
Local<Value> result_v;
135147
if (!parsed.As<Object>()
136148
->Get(context, FIXED_ONE_BYTE_STRING(isolate, "result"))
137149
.ToLocal(&result_v)) {
138-
fprintf(stderr, "Failed to get result from coverage message\n");
139-
return MaybeLocal<String>();
150+
fprintf(stderr, "Failed to get 'result' from %s profile message\n", type);
151+
return MaybeLocal<Object>();
140152
}
141153

142-
if (result_v->IsUndefined()) {
143-
fprintf(stderr, "'result' from coverage message is undefined\n");
144-
return MaybeLocal<String>();
154+
if (!result_v->IsObject()) {
155+
fprintf(
156+
stderr, "'result' from %s profile message is not an object\n", type);
157+
return MaybeLocal<Object>();
145158
}
146159

160+
return result_v.As<Object>();
161+
}
162+
163+
void V8ProfilerConnection::WriteProfile(Local<String> message) {
164+
Local<Context> context = env_->context();
165+
166+
// Get message.result from the response.
167+
Local<Object> result;
168+
if (!ParseProfile(env_, message, type()).ToLocal(&result)) {
169+
return;
170+
}
171+
// Generate the profile output from the subclass.
172+
Local<Object> profile;
173+
if (!GetProfile(result).ToLocal(&profile)) {
174+
return;
175+
}
147176
Local<String> result_s;
148-
if (!v8::JSON::Stringify(context, result_v).ToLocal(&result_s)) {
149-
fprintf(stderr, "Failed to stringify coverage result\n");
150-
return MaybeLocal<String>();
177+
if (!v8::JSON::Stringify(context, profile).ToLocal(&result_s)) {
178+
fprintf(stderr, "Failed to stringify %s profile result\n", type());
179+
return;
151180
}
152181

153-
return result_s;
182+
// Create the directory if necessary.
183+
std::string directory = GetDirectory();
184+
DCHECK(!directory.empty());
185+
if (!EnsureDirectory(directory, type())) {
186+
return;
187+
}
188+
189+
std::string filename = GetFilename();
190+
DCHECK(!filename.empty());
191+
std::string path = directory + kPathSeparator + filename;
192+
193+
WriteResult(env_, path.c_str(), result_s);
194+
}
195+
196+
MaybeLocal<Object> V8CoverageConnection::GetProfile(Local<Object> result) {
197+
return result;
198+
}
199+
200+
std::string V8CoverageConnection::GetDirectory() const {
201+
return env()->coverage_directory();
154202
}
155203

156204
void V8CoverageConnection::Start() {
@@ -184,92 +232,28 @@ void V8CoverageConnection::End() {
184232
DispatchMessage(end);
185233
}
186234

187-
void V8CpuProfilerConnection::OnMessage(
188-
const v8_inspector::StringView& message) {
189-
Debug(env(),
190-
DebugCategory::INSPECTOR_PROFILER,
191-
"Receive cpu profiling message, ending = %s\n",
192-
ending_ ? "true" : "false");
193-
if (!ending_) {
194-
return;
195-
}
196-
Isolate* isolate = env()->isolate();
197-
HandleScope handle_scope(isolate);
198-
Local<Context> context = env()->context();
199-
Context::Scope context_scope(context);
200-
Local<String> result;
201-
if (!String::NewFromTwoByte(isolate,
202-
message.characters16(),
203-
NewStringType::kNormal,
204-
message.length())
205-
.ToLocal(&result)) {
206-
fprintf(stderr, "Failed to convert profiling message\n");
207-
}
208-
WriteCpuProfile(result);
235+
std::string V8CpuProfilerConnection::GetDirectory() const {
236+
return env()->cpu_prof_dir();
209237
}
210238

211-
void V8CpuProfilerConnection::WriteCpuProfile(Local<String> message) {
212-
const std::string& filename = env()->cpu_prof_name();
213-
const std::string& directory = env()->cpu_prof_dir();
214-
CHECK(!filename.empty());
215-
CHECK(!directory.empty());
216-
uv_fs_t req;
217-
int ret = fs::MKDirpSync(nullptr, &req, directory, 0777, nullptr);
218-
uv_fs_req_cleanup(&req);
219-
if (ret < 0 && ret != UV_EEXIST) {
220-
char err_buf[128];
221-
uv_err_name_r(ret, err_buf, sizeof(err_buf));
222-
fprintf(stderr,
223-
"%s: Failed to create cpu profile directory %s\n",
224-
err_buf,
225-
directory.c_str());
226-
return;
227-
}
228-
MaybeLocal<String> result = GetResult(message);
229-
std::string target = directory + kPathSeparator + filename;
230-
if (!result.IsEmpty()) {
231-
WriteResult(target.c_str(), result.ToLocalChecked());
232-
}
239+
std::string V8CpuProfilerConnection::GetFilename() const {
240+
return env()->cpu_prof_name();
233241
}
234242

235-
MaybeLocal<String> V8CpuProfilerConnection::GetResult(Local<String> message) {
236-
Local<Context> context = env()->context();
237-
Isolate* isolate = env()->isolate();
238-
Local<Value> parsed;
239-
if (!v8::JSON::Parse(context, message).ToLocal(&parsed) ||
240-
!parsed->IsObject()) {
241-
fprintf(stderr, "Failed to parse CPU profile result as JSON object\n");
242-
return MaybeLocal<String>();
243-
}
244-
245-
Local<Value> result_v;
246-
if (!parsed.As<Object>()
247-
->Get(context, FIXED_ONE_BYTE_STRING(isolate, "result"))
248-
.ToLocal(&result_v)) {
249-
fprintf(stderr, "Failed to get result from CPU profile message\n");
250-
return MaybeLocal<String>();
251-
}
252-
253-
if (!result_v->IsObject()) {
254-
fprintf(stderr, "'result' from CPU profile message is not an object\n");
255-
return MaybeLocal<String>();
256-
}
257-
243+
MaybeLocal<Object> V8CpuProfilerConnection::GetProfile(Local<Object> result) {
258244
Local<Value> profile_v;
259-
if (!result_v.As<Object>()
260-
->Get(context, FIXED_ONE_BYTE_STRING(isolate, "profile"))
245+
if (!result
246+
->Get(env()->context(),
247+
FIXED_ONE_BYTE_STRING(env()->isolate(), "profile"))
261248
.ToLocal(&profile_v)) {
262249
fprintf(stderr, "'profile' from CPU profile result is undefined\n");
263-
return MaybeLocal<String>();
250+
return MaybeLocal<Object>();
264251
}
265-
266-
Local<String> result_s;
267-
if (!v8::JSON::Stringify(context, profile_v).ToLocal(&result_s)) {
268-
fprintf(stderr, "Failed to stringify CPU profile result\n");
269-
return MaybeLocal<String>();
252+
if (!profile_v->IsObject()) {
253+
fprintf(stderr, "'profile' from CPU profile result is not an Object\n");
254+
return MaybeLocal<Object>();
270255
}
271-
272-
return result_s;
256+
return profile_v.As<Object>();
273257
}
274258

275259
void V8CpuProfilerConnection::Start() {
@@ -298,16 +282,16 @@ void V8CpuProfilerConnection::End() {
298282
// in the future.
299283
void EndStartedProfilers(Environment* env) {
300284
Debug(env, DebugCategory::INSPECTOR_PROFILER, "EndStartedProfilers\n");
301-
V8ProfilerConnection* connection = env->coverage_connection();
285+
V8ProfilerConnection* connection = env->cpu_profiler_connection();
302286
if (connection != nullptr && !connection->ending()) {
303-
Debug(
304-
env, DebugCategory::INSPECTOR_PROFILER, "Ending coverage collection\n");
287+
Debug(env, DebugCategory::INSPECTOR_PROFILER, "Ending cpu profiling\n");
305288
connection->End();
306289
}
307290

308-
connection = env->cpu_profiler_connection();
291+
connection = env->coverage_connection();
309292
if (connection != nullptr && !connection->ending()) {
310-
Debug(env, DebugCategory::INSPECTOR_PROFILER, "Ending cpu profiling\n");
293+
Debug(
294+
env, DebugCategory::INSPECTOR_PROFILER, "Ending coverage collection\n");
311295
connection->End();
312296
}
313297
}

0 commit comments

Comments
 (0)
0