From 0a4401713ad5ebf1a70b77c99ef8bf3257ad84b4 Mon Sep 17 00:00:00 2001 From: Gerhard Stoebich <18708370+Flarna@users.noreply.github.com> Date: Mon, 3 Aug 2020 23:19:54 +0200 Subject: [PATCH] async_hooks: avoid unneeded AsyncResource creation Inspired by the callstack at https://github.com/nodejs/node/issues/34556#issuecomment-666743528 If the wanted store is equal to the active store it's not needed to create an AsyncResource. Refs: https://github.com/nodejs/node/issues/34556#issuecomment-666743528 PR-URL: https://github.com/nodejs/node/pull/34616 Reviewed-By: Anna Henningsen Reviewed-By: Stephen Belanger Reviewed-By: Vladimir de Turckheim Reviewed-By: Andrey Pechkurov --- lib/async_hooks.js | 5 +++++ .../test-async-local-storage-run-resource.js | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/async_hooks.js b/lib/async_hooks.js index 9a4fed9b200c74..cb08993c2da22b 100644 --- a/lib/async_hooks.js +++ b/lib/async_hooks.js @@ -3,6 +3,7 @@ const { NumberIsSafeInteger, ObjectDefineProperties, + ObjectIs, ReflectApply, Symbol, } = primordials; @@ -285,6 +286,10 @@ class AsyncLocalStorage { } run(store, callback, ...args) { + // Avoid creation of an AsyncResource if store is already active + if (ObjectIs(store, this.getStore())) { + return callback(...args); + } const resource = new AsyncResource('AsyncLocalStorage'); return resource.runInAsyncScope(() => { this.enterWith(store); diff --git a/test/async-hooks/test-async-local-storage-run-resource.js b/test/async-hooks/test-async-local-storage-run-resource.js index 9a7479f699246c..21bc70051bd718 100644 --- a/test/async-hooks/test-async-local-storage-run-resource.js +++ b/test/async-hooks/test-async-local-storage-run-resource.js @@ -10,8 +10,21 @@ const asyncLocalStorage = new AsyncLocalStorage(); const outerResource = executionAsyncResource(); -asyncLocalStorage.run(new Map(), () => { - assert.notStrictEqual(executionAsyncResource(), outerResource); +const store = new Map(); +asyncLocalStorage.run(store, () => { + assert.strictEqual(asyncLocalStorage.getStore(), store); + const innerResource = executionAsyncResource(); + assert.notStrictEqual(innerResource, outerResource); + asyncLocalStorage.run(store, () => { + assert.strictEqual(asyncLocalStorage.getStore(), store); + assert.strictEqual(executionAsyncResource(), innerResource); + const otherStore = new Map(); + asyncLocalStorage.run(otherStore, () => { + assert.strictEqual(asyncLocalStorage.getStore(), otherStore); + assert.notStrictEqual(executionAsyncResource(), innerResource); + assert.notStrictEqual(executionAsyncResource(), outerResource); + }); + }); }); assert.strictEqual(executionAsyncResource(), outerResource);