diff --git a/benchmark/async_hooks/async-local-storage-run.js b/benchmark/async_hooks/async-local-storage-run.js new file mode 100644 index 00000000000000..d65abb7047b2e4 --- /dev/null +++ b/benchmark/async_hooks/async-local-storage-run.js @@ -0,0 +1,21 @@ +'use strict'; +const common = require('../common.js'); +const { AsyncLocalStorage } = require('async_hooks'); + +const bench = common.createBenchmark(main, { + n: [1e7] +}); + +async function run(store, n) { + for (let i = 0; i < n; i++) { + await new Promise((resolve) => store.run(i, resolve)); + } +} + +function main({ n }) { + const store = new AsyncLocalStorage(); + bench.start(); + run(store, n).then(() => { + bench.end(n); + }); +} diff --git a/lib/async_hooks.js b/lib/async_hooks.js index 338a4c44f2e9cc..ee8c31fbe0a661 100644 --- a/lib/async_hooks.js +++ b/lib/async_hooks.js @@ -257,7 +257,6 @@ const storageHook = createHook({ } }); -const defaultAlsResourceOpts = { requireManualDestroy: true }; class AsyncLocalStorage { constructor() { this.kResourceStore = Symbol('kResourceStore'); @@ -303,14 +302,19 @@ class AsyncLocalStorage { if (ObjectIs(store, this.getStore())) { return ReflectApply(callback, null, args); } - const resource = new AsyncResource('AsyncLocalStorage', - defaultAlsResourceOpts); - // Calling emitDestroy before runInAsyncScope avoids a try/finally - // It is ok because emitDestroy only schedules calling the hook - return resource.emitDestroy().runInAsyncScope(() => { - this.enterWith(store); + + this._enable(); + + const resource = executionAsyncResource(); + const oldStore = resource[this.kResourceStore]; + + resource[this.kResourceStore] = store; + + try { return ReflectApply(callback, null, args); - }); + } finally { + resource[this.kResourceStore] = oldStore; + } } exit(callback, ...args) { diff --git a/test/async-hooks/test-async-local-storage-run-resource.js b/test/async-hooks/test-async-local-storage-run-resource.js deleted file mode 100644 index 21bc70051bd718..00000000000000 --- a/test/async-hooks/test-async-local-storage-run-resource.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; -require('../common'); -const assert = require('assert'); -const { - AsyncLocalStorage, - executionAsyncResource -} = require('async_hooks'); - -const asyncLocalStorage = new AsyncLocalStorage(); - -const outerResource = executionAsyncResource(); - -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);