Skip to content

Commit

Permalink
src: notify V8 profiler when we're idle
Browse files Browse the repository at this point in the history
Inform V8's CPU profiler when we're idle.  The profiler is
sampling-based but not all samples are created equal; mark the wall
clock time spent in epoll_wait() and friends so profiling tools can
filter it out.  The samples still end up in v8.log but with state=IDLE
rather than state=EXTERNAL.
  • Loading branch information
bnoordhuis committed Oct 3, 2013
1 parent 6820054 commit 57231d5
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/env-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,23 @@ inline uv_idle_t* Environment::immediate_idle_handle() {
return &immediate_idle_handle_;
}

inline Environment* Environment::from_idle_prepare_handle(
uv_prepare_t* handle) {
return CONTAINER_OF(handle, Environment, idle_prepare_handle_);
}

inline uv_prepare_t* Environment::idle_prepare_handle() {
return &idle_prepare_handle_;
}

inline Environment* Environment::from_idle_check_handle(uv_check_t* handle) {
return CONTAINER_OF(handle, Environment, idle_check_handle_);
}

inline uv_check_t* Environment::idle_check_handle() {
return &idle_check_handle_;
}

inline uv_loop_t* Environment::event_loop() const {
return isolate_data()->event_loop();
}
Expand Down
9 changes: 9 additions & 0 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,13 @@ class Environment {
static inline Environment* from_immediate_check_handle(uv_check_t* handle);
inline uv_check_t* immediate_check_handle();
inline uv_idle_t* immediate_idle_handle();

static inline Environment* from_idle_prepare_handle(uv_prepare_t* handle);
inline uv_prepare_t* idle_prepare_handle();

static inline Environment* from_idle_check_handle(uv_check_t* handle);
inline uv_check_t* idle_check_handle();

inline DomainFlag* domain_flag();
inline TickInfo* tick_info();

Expand Down Expand Up @@ -274,6 +281,8 @@ class Environment {
IsolateData* const isolate_data_;
uv_check_t immediate_check_handle_;
uv_idle_t immediate_idle_handle_;
uv_prepare_t idle_prepare_handle_;
uv_check_t idle_check_handle_;
DomainFlag domain_flag_;
TickInfo tick_info_;
uv_timer_t cares_timer_handle_;
Expand Down
32 changes: 32 additions & 0 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "string_bytes.h"
#include "uv.h"
#include "v8-debug.h"
#include "v8-profiler.h"
#include "zlib.h"

#include <assert.h>
Expand Down Expand Up @@ -3205,6 +3206,18 @@ void EmitExit(Environment* env) {
}


void SetIdle(uv_prepare_t* handle, int) {
Environment* env = Environment::from_idle_prepare_handle(handle);
env->isolate()->GetCpuProfiler()->SetIdle(true);
}


void ClearIdle(uv_check_t* handle, int) {
Environment* env = Environment::from_idle_check_handle(handle);
env->isolate()->GetCpuProfiler()->SetIdle(false);
}


Environment* CreateEnvironment(Isolate* isolate,
int argc,
const char* const* argv,
Expand All @@ -3230,6 +3243,25 @@ Environment* CreateEnvironment(Isolate* isolate,
SetupProcessObject(env, argc, argv, exec_argc, exec_argv);
Load(env);

// Inform V8's CPU profiler when we're idle. The profiler is sampling-based
// but not all samples are created equal; mark the wall clock time spent in
// epoll_wait() and friends so profiling tools can filter it out. The samples
// still end up in v8.log but with state=IDLE rather than state=EXTERNAL.
// TODO(bnoordhuis): Only start when profiling. OTOH, the performance impact
// is probably negligible.
// TODO(bnoordhuis) Depends on a libuv implementation detail that we should
// probably fortify in the API contract, namely that the last started prepare
// or check watcher runs first. It's not 100% foolproof; if an add-on starts
// a prepare or check watcher after us, any samples attributed to its callback
// will be recorded with state=IDLE.
uv_prepare_init(env->event_loop(), env->idle_prepare_handle());
uv_prepare_start(env->idle_prepare_handle(), SetIdle);
uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()));

uv_check_init(env->event_loop(), env->idle_check_handle());
uv_check_start(env->idle_check_handle(), ClearIdle);
uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_check_handle()));

return env;
}

Expand Down

0 comments on commit 57231d5

Please sign in to comment.