-
Notifications
You must be signed in to change notification settings - Fork 30.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]> Reviewed-By: Gerhard Stöbich <[email protected]> Reviewed-By: Minwoo Jung <[email protected]>
- Loading branch information
1 parent
3aef68d
commit 97ad72f
Showing
4 changed files
with
186 additions
and
0 deletions.
There are no files selected for viewing
46 changes: 46 additions & 0 deletions
46
benchmark/async_hooks/async-local-storage-getstore-nested-resources.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
'use strict'; | ||
const common = require('../common.js'); | ||
const { AsyncLocalStorage, AsyncResource } = require('async_hooks'); | ||
|
||
/** | ||
* This benchmark verifies the performance of | ||
* `AsyncLocalStorage.getStore()` on propagation through async | ||
* resource scopes. | ||
* | ||
* - AsyncLocalStorage.run() | ||
* - AsyncResource.runInAsyncScope | ||
* - AsyncResource.runInAsyncScope | ||
* ... | ||
* - AsyncResource.runInAsyncScope | ||
* - AsyncLocalStorage.getStore() | ||
*/ | ||
const bench = common.createBenchmark(main, { | ||
resourceCount: [10, 100, 1000], | ||
n: [1e4], | ||
}); | ||
|
||
function runBenchmark(store, n) { | ||
for (let i = 0; i < n; i++) { | ||
store.getStore(); | ||
} | ||
} | ||
|
||
function runInAsyncScopes(resourceCount, cb, i = 0) { | ||
if (i === resourceCount) { | ||
cb(); | ||
} else { | ||
const resource = new AsyncResource('noop'); | ||
resource.runInAsyncScope(() => { | ||
runInAsyncScopes(resourceCount, cb, i + 1); | ||
}); | ||
} | ||
} | ||
|
||
function main({ n, resourceCount }) { | ||
const store = new AsyncLocalStorage(); | ||
runInAsyncScopes(resourceCount, () => { | ||
bench.start(); | ||
runBenchmark(store, n); | ||
bench.end(n); | ||
}); | ||
} |
46 changes: 46 additions & 0 deletions
46
benchmark/async_hooks/async-local-storage-getstore-nested-run.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
'use strict'; | ||
const common = require('../common.js'); | ||
const { AsyncLocalStorage } = require('async_hooks'); | ||
|
||
/** | ||
* This benchmark verifies the performance of | ||
* `AsyncLocalStorage.getStore()` on multiple `AsyncLocalStorage` instances | ||
* nested `AsyncLocalStorage.run()`s. | ||
* | ||
* - AsyncLocalStorage1.run() | ||
* - AsyncLocalStorage2.run() | ||
* ... | ||
* - AsyncLocalStorageN.run() | ||
* - AsyncLocalStorage1.getStore() | ||
*/ | ||
const bench = common.createBenchmark(main, { | ||
sotrageCount: [1, 10, 100], | ||
n: [1e4], | ||
}); | ||
|
||
function runBenchmark(store, n) { | ||
for (let idx = 0; idx < n; idx++) { | ||
store.getStore(); | ||
} | ||
} | ||
|
||
function runStores(stores, value, cb, idx = 0) { | ||
if (idx === stores.length) { | ||
cb(); | ||
} else { | ||
stores[idx].run(value, () => { | ||
runStores(stores, value, cb, idx + 1); | ||
}); | ||
} | ||
} | ||
|
||
function main({ n, sotrageCount }) { | ||
const stores = new Array(sotrageCount).fill(0).map(() => new AsyncLocalStorage()); | ||
const contextValue = {}; | ||
|
||
runStores(stores, contextValue, () => { | ||
bench.start(); | ||
runBenchmark(stores[0], n); | ||
bench.end(n); | ||
}); | ||
} |
46 changes: 46 additions & 0 deletions
46
benchmark/async_hooks/async-local-storage-propagate-asyncresource.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
'use strict'; | ||
const common = require('../common.js'); | ||
const { AsyncLocalStorage, AsyncResource } = require('async_hooks'); | ||
|
||
/** | ||
* This benchmark verifies the performance degradation of | ||
* async resource propagation on the increasing number of | ||
* active `AsyncLocalStorage`s. | ||
* | ||
* - AsyncLocalStorage.run() * storageCount | ||
* - new AsyncResource() | ||
* - new AsyncResource() | ||
* ... | ||
* - N new Asyncresource() | ||
*/ | ||
const bench = common.createBenchmark(main, { | ||
storageCount: [0, 1, 10, 100], | ||
n: [1e3], | ||
}); | ||
|
||
function runStores(stores, value, cb, idx = 0) { | ||
if (idx === stores.length) { | ||
cb(); | ||
} else { | ||
stores[idx].run(value, () => { | ||
runStores(stores, value, cb, idx + 1); | ||
}); | ||
} | ||
} | ||
|
||
function runBenchmark(n) { | ||
for (let i = 0; i < n; i++) { | ||
new AsyncResource('noop'); | ||
} | ||
} | ||
|
||
function main({ n, storageCount }) { | ||
const stores = new Array(storageCount).fill(0).map(() => new AsyncLocalStorage()); | ||
const contextValue = {}; | ||
|
||
runStores(stores, contextValue, () => { | ||
bench.start(); | ||
runBenchmark(n); | ||
bench.end(n); | ||
}); | ||
} |
48 changes: 48 additions & 0 deletions
48
benchmark/async_hooks/async-local-storage-propagate-promise.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
'use strict'; | ||
const common = require('../common.js'); | ||
const { AsyncLocalStorage } = require('async_hooks'); | ||
|
||
/** | ||
* This benchmark verifies the performance degradation of | ||
* async resource propagation on the increasing number of | ||
* active `AsyncLocalStorage`s. | ||
* | ||
* - AsyncLocalStorage.run() | ||
* - Promise | ||
* - Promise | ||
* ... | ||
* - Promise | ||
*/ | ||
const bench = common.createBenchmark(main, { | ||
storageCount: [0, 1, 10, 100], | ||
n: [1e5], | ||
}); | ||
|
||
function runStores(stores, value, cb, idx = 0) { | ||
if (idx === stores.length) { | ||
cb(); | ||
} else { | ||
stores[idx].run(value, () => { | ||
runStores(stores, value, cb, idx + 1); | ||
}); | ||
} | ||
} | ||
|
||
async function runBenchmark(n) { | ||
for (let i = 0; i < n; i++) { | ||
// Avoid creating additional ticks. | ||
await undefined; | ||
} | ||
} | ||
|
||
function main({ n, storageCount }) { | ||
const stores = new Array(storageCount).fill(0).map(() => new AsyncLocalStorage()); | ||
const contextValue = {}; | ||
|
||
runStores(stores, contextValue, () => { | ||
bench.start(); | ||
runBenchmark(n).then(() => { | ||
bench.end(n); | ||
}); | ||
}); | ||
} |