| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent eb6ea85 commit 6aa1ed2
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -61,6 +61,8 @@ InternalCallbackScope::InternalCallbackScope(Environment* env, | |||
| 61 | 61 | // If you hit this assertion, you forgot to enter the v8::Context first. | |
| 62 | 62 | CHECK_EQ(Environment::GetCurrent(env->isolate()), env); | |
| 63 | 63 | ||
| 64 | + env->isolate()->SetIdle(false); | ||
| 65 | + | ||
| 64 | 66 | env->async_hooks()->push_async_context( | |
| 65 | 67 | async_context_.async_id, async_context_.trigger_async_id, object); | |
| 66 | 68 | ||
@@ -82,6 +84,8 @@ void InternalCallbackScope::Close() { | |||
| 82 | 84 | if (closed_) return; | |
| 83 | 85 | closed_ = true; | |
| 84 | 86 | ||
| 87 | + auto idle = OnScopeLeave([&]() { env_->isolate()->SetIdle(true); }); | ||
| 88 | + | ||
| 85 | 89 | if (!env_->can_call_into_js()) return; | |
| 86 | 90 | auto perform_stopping_check = [&]() { | |
| 87 | 91 | if (env_->is_stopping()) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -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 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -919,6 +919,8 @@ class Environment : public MemoryRetainer { | |||
| 919 | 919 | inline void AssignToContext(v8::Local<v8::Context> context, | |
| 920 | 920 | const ContextInfo& info); | |
| 921 | 921 | ||
| 922 | + void StartProfilerIdleNotifier(); | ||
| 923 | + | ||
| 922 | 924 | inline v8::Isolate* isolate() const; | |
| 923 | 925 | inline uv_loop_t* event_loop() const; | |
| 924 | 926 | inline void TryLoadAddon( | |
@@ -1252,6 +1254,8 @@ class Environment : public MemoryRetainer { | |||
| 1252 | 1254 | uv_timer_t timer_handle_; | |
| 1253 | 1255 | uv_check_t immediate_check_handle_; | |
| 1254 | 1256 | uv_idle_t immediate_idle_handle_; | |
| 1257 | + uv_prepare_t idle_prepare_handle_; | ||
| 1258 | + uv_check_t idle_check_handle_; | ||
| 1255 | 1259 | uv_async_t task_queues_async_; | |
| 1256 | 1260 | int64_t task_queues_async_refs_ = 0; | |
| 1257 | 1261 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,43 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../common'); | ||
| 3 | + | ||
| 4 | + common.skipIfInspectorDisabled(); | ||
| 5 | + | ||
| 6 | + const assert = require('assert'); | ||
| 7 | + const { Session } = require('inspector'); | ||
| 8 | + const { promisify } = require('util'); | ||
| 9 | + | ||
| 10 | + const sleep = promisify(setTimeout); | ||
| 11 | + | ||
| 12 | + async function test() { | ||
| 13 | + const inspector = new Session(); | ||
| 14 | + inspector.connect(); | ||
| 15 | + | ||
| 16 | + inspector.post('Profiler.enable'); | ||
| 17 | + inspector.post('Profiler.start'); | ||
| 18 | + | ||
| 19 | + await sleep(1000); | ||
| 20 | + | ||
| 21 | + const { profile } = await new Promise((resolve, reject) => { | ||
| 22 | + inspector.post('Profiler.stop', (err, params) => { | ||
| 23 | + if (err) return reject(err); | ||
| 24 | + resolve(params); | ||
| 25 | + }); | ||
| 26 | + }); | ||
| 27 | + | ||
| 28 | + let hasIdle = false; | ||
| 29 | + for (const node of profile.nodes) { | ||
| 30 | + if (node.callFrame.functionName === '(idle)') { | ||
| 31 | + hasIdle = true; | ||
| 32 | + break; | ||
| 33 | + } | ||
| 34 | + } | ||
| 35 | + assert(hasIdle); | ||
| 36 | + | ||
| 37 | + inspector.post('Profiler.disable'); | ||
| 38 | + inspector.disconnect(); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + test().then(common.mustCall(() => { | ||
| 42 | + console.log('Done!'); | ||
| 43 | + })); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments