let's say we have a async function like following:
let counter = 1;
async function async_func() {
return new Promise((resolve, reject) => {
setTimeout(function() {
resolve(counter++);
}, 500);
})
}
It's only task to wait 500ms
and then return latest counter
.
Let's call this async_func
function using async-await
and see how much time it takes for different range.
Sample 1
(async () => {
console.time('async-await');
for ( let i=0; i<n; i++ ) {
await async_func();
}
console.timeEnd('async-await');
})();
And time spend
n # times
------------------------------------
10 # 5.10s
------------------------------------
100 # 50.994s
------------------------------------
1000 # 8:28.113 (m:ss.mmm)
------------------------------------
Sample 1's code run sequentially. This will be use for absolute sequence. Although there is another way (given below) which will work in the same manner without any async-await
. As you can see, for 1000
call takes 8:28.113 (m:ss.mmm)
which is way too much (this test run on local, it can be changed based on computer power).
Sample 2
(async () => {
let finalResult = [];
console.time('reduce-sync');
await Array.from({ length: n }).reduce((promise, dt) => {
return promise.then(
() =>
async_func()
.then(result => finalResult.push(result))
);
}, Promise.resolve());
console.timeEnd('reduce-sync');
})();
Sample 2's code also run sequentially and performance is almost same. What we are doing here?
array.reduce((promise, dt) => {}, Promise.resolve())
, here accumulator
is promise, so we can use promise.then(....)
Let's try to improve performance with sacrificing absolute sequential execution.
Sample 3
(async () => {
console.time('reduce-semi-sequential');
const oldData = Array.from({ length: n });
const newData = [];
while (oldData.length) newData.push(oldData.splice(0, 4));
let finalResult = [];
await newData.reduce((promise, currentList) => {
return promise.then(() =>
Promise.all(
currentList.map((current) => async_func(),
),
).then((result) => {
finalResult = [...finalResult, ...result];
return Promise.resolve();
}),
);
}, Promise.resolve());
console.timeEnd('reduce-semi-sequential');
})();
And time spend
n # times
------------------------------------
10 # 1.527s
------------------------------------
100 # 12.757s
------------------------------------
1000 # 2:07.140 (m:ss.mmm)
------------------------------------
10000 # 21:10.670 (m:ss.mmm)
------------------------------------
as we can see, performance is much improved. Here first we are change 1-D
[1,2,3,4,5,6,7,8,9,10]
array to 2-D
array
[
[1,2,3,4], // 0-group
[5,6,7,8], // 1-index
[9,10] // 2-index
now every 0/1/2
-group will run sequentially, inside each group will run in parallel.
It could be improve if we increase newData.push(oldData.splice(0, 4)
total array size from 4
to higher. For example, by changing newData.push(oldData.splice(0, 4)
to newData.push(oldData.splice(0, 10)
, I get following result
n # times
------------------------------------
1,000 # 5.126s
------------------------------------
10,000 # 51.081s
------------------------------------
100,000 # 8:29.471 (m:ss.mmm)
------------------------------------
1,000,000 # 1:26:01.277 (h:mm:ss.mmm)
------------------------------------
And what if we don't need sequential execution, let's try to run in parallel
(async () => {
console.time('promise-parallel');
await Promise.all(
Array.from({ length: n}).map( (i) => async_func())
);
console.timeEnd('promise-parallel');
})();
and time execution
n # times
------------------------------------
10 # 502.277ms
------------------------------------
100 # 504.385ms
------------------------------------
1,000 # 514.173ms
------------------------------------
10,000 # 547.021ms
------------------------------------
100,000 # 3.649s
------------------------------------
as you see, run in parallel
improve code performance a lot. But there is some issues also. For example, if array size is very high like 1M
(depends of CPU), then we will get RangeError
like following
RangeError: Too many elements passed to Promise.all
at Function.allSettled (<anonymous>)
.................
.................
Top comments (0)