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)