From 5eb30aa205b445e99117a8d7f652cee2015c5053 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 --- 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 6fa0aa0abadd68..c5342deb3537ce 100644 --- a/lib/async_hooks.js +++ b/lib/async_hooks.js @@ -3,6 +3,7 @@ const { NumberIsSafeInteger, ObjectDefineProperties, + ObjectIs, ReflectApply, Symbol, } = primordials; @@ -284,6 +285,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);