From 28abbfd594ba39c28901ad1ed97586275360574b Mon Sep 17 00:00:00 2001 From: Andrey Pechkurov Date: Sun, 22 Mar 2020 21:53:52 +0300 Subject: [PATCH] async_hooks: move to lazy destroy hook registration in AsyncResource MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/32429 Reviewed-By: Gerhard Stöbich Reviewed-By: Vladimir de Turckheim --- benchmark/async_hooks/gc-tracking.js | 11 ++++++++++- doc/api/async_hooks.md | 2 ++ lib/async_hooks.js | 3 ++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/benchmark/async_hooks/gc-tracking.js b/benchmark/async_hooks/gc-tracking.js index 030b5f8e1934f8..4a59a5a4b655c5 100644 --- a/benchmark/async_hooks/gc-tracking.js +++ b/benchmark/async_hooks/gc-tracking.js @@ -1,11 +1,12 @@ 'use strict'; const common = require('../common.js'); -const { AsyncResource } = require('async_hooks'); +const { createHook, AsyncResource } = require('async_hooks'); const bench = common.createBenchmark(main, { n: [1e6], method: [ 'trackingEnabled', + 'trackingEnabledWithDestroyHook', 'trackingDisabled', ] }, { @@ -30,6 +31,14 @@ function main({ n, method }) { } endAfterGC(n); break; + case 'trackingEnabledWithDestroyHook': + createHook({ destroy: () => {} }).enable(); + bench.start(); + for (let i = 0; i < n; i++) { + new AsyncResource('foobar'); + } + endAfterGC(n); + break; case 'trackingDisabled': bench.start(); for (let i = 0; i < n; i++) { diff --git a/doc/api/async_hooks.md b/doc/api/async_hooks.md index 5d526d223c8ba1..813f2735ea5141 100644 --- a/doc/api/async_hooks.md +++ b/doc/api/async_hooks.md @@ -629,6 +629,8 @@ asyncResource.triggerAsyncId(); when the object is garbage collected. This usually does not need to be set (even if `emitDestroy` is called manually), unless the resource's `asyncId` is retrieved and the sensitive API's `emitDestroy` is called with it. + When set to `false`, the `emitDestroy` call on garbage collection + will only take place if there is at least one active `destroy` hook. **Default:** `false`. Example usage: diff --git a/lib/async_hooks.js b/lib/async_hooks.js index 009f15c83b1d8e..0e77e7402b5282 100644 --- a/lib/async_hooks.js +++ b/lib/async_hooks.js @@ -35,6 +35,7 @@ const { emitDestroy, enabledHooksExist, initHooksExist, + destroyHooksExist, } = internal_async_hooks; // Get symbols @@ -167,7 +168,7 @@ class AsyncResource { emitInit(asyncId, type, triggerAsyncId, this); } - if (!requireManualDestroy) { + if (!requireManualDestroy && destroyHooksExist()) { // This prop name (destroyed) has to be synchronized with C++ const destroyed = { destroyed: false }; this[destroyedSymbol] = destroyed;