@@ -495,6 +495,13 @@ void Environment::InitializeLibuv() { |
495 | 495 |
|
496 | 496 | uv_check_start(immediate_check_handle(), CheckImmediate); |
497 | 497 |
|
| 498 | + // Inform V8's CPU profiler when we're idle. The profiler is sampling-based |
| 499 | + // but not all samples are created equal; mark the wall clock time spent in |
| 500 | + // epoll_wait() and friends so profiling tools can filter it out. The samples |
| 501 | + // still end up in v8.log but with state=IDLE rather than state=EXTERNAL. |
| 502 | + uv_prepare_init(event_loop(), &idle_prepare_handle_); |
| 503 | + uv_check_init(event_loop(), &idle_check_handle_); |
| 504 | + |
498 | 505 | uv_async_init( |
499 | 506 | event_loop(), |
500 | 507 | &task_queues_async_, |
@@ -505,6 +512,8 @@ void Environment::InitializeLibuv() { |
505 | 512 | Context::Scope context_scope(env->context()); |
506 | 513 | env->RunAndClearNativeImmediates(); |
507 | 514 | }); |
| 515 | + uv_unref(reinterpret_cast<uv_handle_t*>(&idle_prepare_handle_)); |
| 516 | + uv_unref(reinterpret_cast<uv_handle_t*>(&idle_check_handle_)); |
508 | 517 | uv_unref(reinterpret_cast<uv_handle_t*>(&task_queues_async_)); |
509 | 518 |
|
510 | 519 | { |
@@ -521,6 +530,8 @@ void Environment::InitializeLibuv() { |
521 | 530 | // the one environment per process setup, but will be called in |
522 | 531 | // FreeEnvironment. |
523 | 532 | RegisterHandleCleanups(); |
| 533 | + |
| 534 | + StartProfilerIdleNotifier(); |
524 | 535 | } |
525 | 536 |
|
526 | 537 | void Environment::ExitEnv() { |
@@ -548,6 +559,8 @@ void Environment::RegisterHandleCleanups() { |
548 | 559 | register_handle(reinterpret_cast<uv_handle_t*>(timer_handle())); |
549 | 560 | register_handle(reinterpret_cast<uv_handle_t*>(immediate_check_handle())); |
550 | 561 | register_handle(reinterpret_cast<uv_handle_t*>(immediate_idle_handle())); |
| 562 | + register_handle(reinterpret_cast<uv_handle_t*>(&idle_prepare_handle_)); |
| 563 | + register_handle(reinterpret_cast<uv_handle_t*>(&idle_check_handle_)); |
551 | 564 | register_handle(reinterpret_cast<uv_handle_t*>(&task_queues_async_)); |
552 | 565 | } |
553 | 566 |
|
@@ -579,6 +592,17 @@ void Environment::CleanupHandles() { |
579 | 592 | } |
580 | 593 | } |
581 | 594 |
|
| 595 | +void Environment::StartProfilerIdleNotifier() { |
| 596 | + uv_prepare_start(&idle_prepare_handle_, [](uv_prepare_t* handle) { |
| 597 | + Environment* env = ContainerOf(&Environment::idle_prepare_handle_, handle); |
| 598 | + env->isolate()->SetIdle(true); |
| 599 | + }); |
| 600 | + uv_check_start(&idle_check_handle_, [](uv_check_t* handle) { |
| 601 | + Environment* env = ContainerOf(&Environment::idle_check_handle_, handle); |
| 602 | + env->isolate()->SetIdle(false); |
| 603 | + }); |
| 604 | +} |
| 605 | + |
582 | 606 | void Environment::PrintSyncTrace() const { |
583 | 607 | if (!trace_sync_io_) return; |
584 | 608 |
|
|