-
-
Notifications
You must be signed in to change notification settings - Fork 32.6k
Description
- Version: 12.18.3
- Platform: macos
- Subsystem: async_hooks
What steps will reproduce the bug?
const { AsyncLocalStorage } = require('async_hooks');
const asyncLocalStorage = new AsyncLocalStorage();
let fn = async () => /test/.test('test');
let runWithExpiry = async (expiry, fn) => {
let iterations = 0;
while (Date.now() < expiry) {
await fn();
iterations++;
}
return iterations;
};
(async () => {
console.log(`Performed ${await runWithExpiry(Date.now() + 100, fn)} iterations to warmup`);
asyncLocalStorage.run({}, () => {});
let withAls = await runWithExpiry(Date.now() + 1000, fn);
console.log(`Performed ${withAls} iterations (with ALS enabled)`);
asyncLocalStorage.disable();
let withoutAls = await runWithExpiry(Date.now() + 1000, fn);
console.log(`Performed ${withoutAls} iterations (with ALS disabled)`);
console.log('ALS penalty: ' + Math.round((1 - (withAls / withoutAls)) * 10000) / 100 + '%');
})();
Output:
Performed 180407 iterations to warmup
Performed 205741 iterations (with ALS enabled)
Performed 6446728 iterations (with ALS disabled)
ALS penalty: 96.8%
How often does it reproduce? Is there a required condition?
In any case that await
is used.
What is the expected behavior?
Should be around 10% penalty.
What do you see instead?
I see 97% reduction in performance.
Additional information
I've played in the past with a Zone polyfill of my own (zone-polyfill
), and at the beginning I tried using the stack traces that's generated in latest V8 versions, where they keep their context after await
calls.
Combining that with the basic technique to track context, I was able to track the zone but due to the string nature of the stack traces - I had to map them in the memory but there was no WeakMap
available. Using a NAN solution I got to about 15% penalty.
Now assuming that these capabilities are available on the c++ side and much more natively, with the option to directly leverage the compiler instead of generating stack traces to query for info - I'd assume max 10% penalty with a native implementation.