Skip to content

Commit 97ad72f

Browse files
legendecasdanielleadams
authored andcommitted
async_hooks: add async local storage propagation benchmarks
Add micro-benchmarks to verify the performance degradation related to the number of active `AsyncLocalStorage`s. With these benchmarks, trying to improve the async context propagation to be an O(1) operation, which is an operation more frequent compared to `asyncLocalStorage.run` and `asyncLocalStorage.getStore`. PR-URL: #46414 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
1 parent 3aef68d commit 97ad72f

4 files changed

Lines changed: 186 additions & 0 deletions
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
constcommon=require('../common.js');
3+
const{ AsyncLocalStorage, AsyncResource }=require('async_hooks');
4+
5+
/**
6+
* This benchmark verifies the performance of
7+
* `AsyncLocalStorage.getStore()` on propagation through async
8+
* resource scopes.
9+
*
10+
* - AsyncLocalStorage.run()
11+
* - AsyncResource.runInAsyncScope
12+
* - AsyncResource.runInAsyncScope
13+
* ...
14+
* - AsyncResource.runInAsyncScope
15+
* - AsyncLocalStorage.getStore()
16+
*/
17+
constbench=common.createBenchmark(main,{
18+
resourceCount: [10,100,1000],
19+
n: [1e4],
20+
});
21+
22+
functionrunBenchmark(store,n){
23+
for(leti=0;i<n;i++){
24+
store.getStore();
25+
}
26+
}
27+
28+
functionrunInAsyncScopes(resourceCount,cb,i=0){
29+
if(i===resourceCount){
30+
cb();
31+
}else{
32+
constresource=newAsyncResource('noop');
33+
resource.runInAsyncScope(()=>{
34+
runInAsyncScopes(resourceCount,cb,i+1);
35+
});
36+
}
37+
}
38+
39+
functionmain({ n, resourceCount }){
40+
conststore=newAsyncLocalStorage();
41+
runInAsyncScopes(resourceCount,()=>{
42+
bench.start();
43+
runBenchmark(store,n);
44+
bench.end(n);
45+
});
46+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
constcommon=require('../common.js');
3+
const{ AsyncLocalStorage }=require('async_hooks');
4+
5+
/**
6+
* This benchmark verifies the performance of
7+
* `AsyncLocalStorage.getStore()` on multiple `AsyncLocalStorage` instances
8+
* nested `AsyncLocalStorage.run()`s.
9+
*
10+
* - AsyncLocalStorage1.run()
11+
* - AsyncLocalStorage2.run()
12+
* ...
13+
* - AsyncLocalStorageN.run()
14+
* - AsyncLocalStorage1.getStore()
15+
*/
16+
constbench=common.createBenchmark(main,{
17+
sotrageCount: [1,10,100],
18+
n: [1e4],
19+
});
20+
21+
functionrunBenchmark(store,n){
22+
for(letidx=0;idx<n;idx++){
23+
store.getStore();
24+
}
25+
}
26+
27+
functionrunStores(stores,value,cb,idx=0){
28+
if(idx===stores.length){
29+
cb();
30+
}else{
31+
stores[idx].run(value,()=>{
32+
runStores(stores,value,cb,idx+1);
33+
});
34+
}
35+
}
36+
37+
functionmain({ n, sotrageCount }){
38+
conststores=newArray(sotrageCount).fill(0).map(()=>newAsyncLocalStorage());
39+
constcontextValue={};
40+
41+
runStores(stores,contextValue,()=>{
42+
bench.start();
43+
runBenchmark(stores[0],n);
44+
bench.end(n);
45+
});
46+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
constcommon=require('../common.js');
3+
const{ AsyncLocalStorage, AsyncResource }=require('async_hooks');
4+
5+
/**
6+
* This benchmark verifies the performance degradation of
7+
* async resource propagation on the increasing number of
8+
* active `AsyncLocalStorage`s.
9+
*
10+
* - AsyncLocalStorage.run() * storageCount
11+
* - new AsyncResource()
12+
* - new AsyncResource()
13+
* ...
14+
* - N new Asyncresource()
15+
*/
16+
constbench=common.createBenchmark(main,{
17+
storageCount: [0,1,10,100],
18+
n: [1e3],
19+
});
20+
21+
functionrunStores(stores,value,cb,idx=0){
22+
if(idx===stores.length){
23+
cb();
24+
}else{
25+
stores[idx].run(value,()=>{
26+
runStores(stores,value,cb,idx+1);
27+
});
28+
}
29+
}
30+
31+
functionrunBenchmark(n){
32+
for(leti=0;i<n;i++){
33+
newAsyncResource('noop');
34+
}
35+
}
36+
37+
functionmain({ n, storageCount }){
38+
conststores=newArray(storageCount).fill(0).map(()=>newAsyncLocalStorage());
39+
constcontextValue={};
40+
41+
runStores(stores,contextValue,()=>{
42+
bench.start();
43+
runBenchmark(n);
44+
bench.end(n);
45+
});
46+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
'use strict';
2+
constcommon=require('../common.js');
3+
const{ AsyncLocalStorage }=require('async_hooks');
4+
5+
/**
6+
* This benchmark verifies the performance degradation of
7+
* async resource propagation on the increasing number of
8+
* active `AsyncLocalStorage`s.
9+
*
10+
* - AsyncLocalStorage.run()
11+
* - Promise
12+
* - Promise
13+
* ...
14+
* - Promise
15+
*/
16+
constbench=common.createBenchmark(main,{
17+
storageCount: [0,1,10,100],
18+
n: [1e5],
19+
});
20+
21+
functionrunStores(stores,value,cb,idx=0){
22+
if(idx===stores.length){
23+
cb();
24+
}else{
25+
stores[idx].run(value,()=>{
26+
runStores(stores,value,cb,idx+1);
27+
});
28+
}
29+
}
30+
31+
asyncfunctionrunBenchmark(n){
32+
for(leti=0;i<n;i++){
33+
// Avoid creating additional ticks.
34+
awaitundefined;
35+
}
36+
}
37+
38+
functionmain({ n, storageCount }){
39+
conststores=newArray(storageCount).fill(0).map(()=>newAsyncLocalStorage());
40+
constcontextValue={};
41+
42+
runStores(stores,contextValue,()=>{
43+
bench.start();
44+
runBenchmark(n).then(()=>{
45+
bench.end(n);
46+
});
47+
});
48+
}

0 commit comments

Comments
 (0)