-
Notifications
You must be signed in to change notification settings - Fork 29.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
inspector: implement --cpu-prof-interval #27535
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
#include "inspector_profiler.h" | ||
#include <sstream> | ||
#include "base_object-inl.h" | ||
#include "debug_utils.h" | ||
#include "node_file.h" | ||
|
@@ -20,7 +21,6 @@ using v8::Object; | |
using v8::String; | ||
using v8::Value; | ||
|
||
using v8_inspector::StringBuffer; | ||
using v8_inspector::StringView; | ||
|
||
#ifdef _WIN32 | ||
|
@@ -33,21 +33,34 @@ const char* const kPathSeparator = "/"; | |
#define CWD_BUFSIZE (PATH_MAX) | ||
#endif | ||
|
||
std::unique_ptr<StringBuffer> ToProtocolString(Isolate* isolate, | ||
Local<Value> value) { | ||
TwoByteValue buffer(isolate, value); | ||
return StringBuffer::create(StringView(*buffer, buffer.length())); | ||
} | ||
|
||
V8ProfilerConnection::V8ProfilerConnection(Environment* env) | ||
: session_(env->inspector_agent()->Connect( | ||
std::make_unique<V8ProfilerConnection::V8ProfilerSessionDelegate>( | ||
this), | ||
false)), | ||
env_(env) {} | ||
|
||
void V8ProfilerConnection::DispatchMessage(Local<String> message) { | ||
session_->Dispatch(ToProtocolString(env()->isolate(), message)->string()); | ||
size_t V8ProfilerConnection::DispatchMessage(const char* method, | ||
const char* params) { | ||
std::stringstream ss; | ||
size_t id = next_id(); | ||
ss << R"({ "id": )" << id; | ||
DCHECK(method != nullptr); | ||
ss << R"(, "method": ")" << method << '"'; | ||
if (params != nullptr) { | ||
ss << R"(, "params": )" << params; | ||
} | ||
ss << " }"; | ||
std::string message = ss.str(); | ||
const uint8_t* message_data = | ||
reinterpret_cast<const uint8_t*>(message.c_str()); | ||
Debug(env(), | ||
DebugCategory::INSPECTOR_PROFILER, | ||
"Dispatching message %s\n", | ||
message.c_str()); | ||
session_->Dispatch(StringView(message_data, message.length())); | ||
// TODO(joyeecheung): use this to identify the ending message. | ||
return id; | ||
} | ||
|
||
static void WriteResult(Environment* env, | ||
|
@@ -202,34 +215,15 @@ std::string V8CoverageConnection::GetDirectory() const { | |
} | ||
|
||
void V8CoverageConnection::Start() { | ||
Debug(env(), | ||
DebugCategory::INSPECTOR_PROFILER, | ||
"Sending Profiler.startPreciseCoverage\n"); | ||
Isolate* isolate = env()->isolate(); | ||
Local<String> enable = FIXED_ONE_BYTE_STRING( | ||
isolate, R"({"id": 1, "method": "Profiler.enable"})"); | ||
Local<String> start = FIXED_ONE_BYTE_STRING(isolate, R"({ | ||
"id": 2, | ||
"method": "Profiler.startPreciseCoverage", | ||
"params": { "callCount": true, "detailed": true } | ||
})"); | ||
DispatchMessage(enable); | ||
DispatchMessage(start); | ||
DispatchMessage("Profiler.enable"); | ||
DispatchMessage("Profiler.startPreciseCoverage", | ||
R"({ "callCount": true, "detailed": true })"); | ||
} | ||
|
||
void V8CoverageConnection::End() { | ||
CHECK_EQ(ending_, false); | ||
ending_ = true; | ||
Debug(env(), | ||
DebugCategory::INSPECTOR_PROFILER, | ||
"Sending Profiler.takePreciseCoverage\n"); | ||
Isolate* isolate = env()->isolate(); | ||
HandleScope scope(isolate); | ||
Local<String> end = FIXED_ONE_BYTE_STRING(isolate, R"({ | ||
"id": 3, | ||
"method": "Profiler.takePreciseCoverage" | ||
})"); | ||
DispatchMessage(end); | ||
DispatchMessage("Profiler.takePreciseCoverage"); | ||
} | ||
|
||
std::string V8CpuProfilerConnection::GetDirectory() const { | ||
|
@@ -257,25 +251,18 @@ MaybeLocal<Object> V8CpuProfilerConnection::GetProfile(Local<Object> result) { | |
} | ||
|
||
void V8CpuProfilerConnection::Start() { | ||
Debug(env(), DebugCategory::INSPECTOR_PROFILER, "Sending Profiler.start\n"); | ||
Isolate* isolate = env()->isolate(); | ||
Local<String> enable = FIXED_ONE_BYTE_STRING( | ||
isolate, R"({"id": 1, "method": "Profiler.enable"})"); | ||
Local<String> start = FIXED_ONE_BYTE_STRING( | ||
isolate, R"({"id": 2, "method": "Profiler.start"})"); | ||
DispatchMessage(enable); | ||
DispatchMessage(start); | ||
DispatchMessage("Profiler.enable"); | ||
DispatchMessage("Profiler.start"); | ||
std::string params = R"({ "interval": )"; | ||
params += std::to_string(env()->cpu_prof_interval()); | ||
params += " }"; | ||
DispatchMessage("Profiler.setSamplingInterval", params.c_str()); | ||
} | ||
|
||
void V8CpuProfilerConnection::End() { | ||
CHECK_EQ(ending_, false); | ||
ending_ = true; | ||
Debug(env(), DebugCategory::INSPECTOR_PROFILER, "Sending Profiler.stop\n"); | ||
Isolate* isolate = env()->isolate(); | ||
HandleScope scope(isolate); | ||
Local<String> end = | ||
FIXED_ONE_BYTE_STRING(isolate, R"({"id": 3, "method": "Profiler.stop"})"); | ||
DispatchMessage(end); | ||
DispatchMessage("Profiler.stop"); | ||
} | ||
|
||
// For now, we only support coverage profiling, but we may add more | ||
|
@@ -320,6 +307,7 @@ void StartProfilers(Environment* env) { | |
} | ||
if (env->options()->cpu_prof) { | ||
const std::string& dir = env->options()->cpu_prof_dir; | ||
env->set_cpu_prof_interval(env->options()->cpu_prof_interval); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could just use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking about making this profiling capability available on-demand during runtime in the future, as requested here, in that case I think it makes more sense to put the options on the Environment itself (or in a separate struct when we have too many of them), because these may not come from CLI at that point. |
||
env->set_cpu_prof_dir(dir.empty() ? GetCwd() : dir); | ||
if (env->options()->cpu_prof_name.empty()) { | ||
DiagnosticFilename filename(env, "CPU", "cpuprofile"); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really liking the added clarity in these methods! 👍