Logo

dev-resources.site

for different kinds of informations.

JavaScript async call analysis

Published at
2/12/2024
Categories
javascript
async
webdev
Author
sabbir9920
Categories
3 categories in total
javascript
open
async
open
webdev
open
Author
10 person written this
sabbir9920
open
JavaScript async call analysis

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); 
  })
}

Enter fullscreen mode Exit fullscreen mode

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');
})();
Enter fullscreen mode Exit fullscreen mode

And time spend

    n     #    times
------------------------------------
   10     #    5.10s 
------------------------------------
   100    #    50.994s
------------------------------------
  1000    #    8:28.113 (m:ss.mmm)
------------------------------------
Enter fullscreen mode Exit fullscreen mode

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');
})();
Enter fullscreen mode Exit fullscreen mode

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');
})();
Enter fullscreen mode Exit fullscreen mode

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)
------------------------------------
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)
------------------------------------
Enter fullscreen mode Exit fullscreen mode

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');
})();

Enter fullscreen mode Exit fullscreen mode

and time execution

     n     #    times
------------------------------------
     10    #    502.277ms
------------------------------------
    100    #    504.385ms
------------------------------------
   1,000   #    514.173ms
------------------------------------
  10,000   #    547.021ms
------------------------------------
  100,000  #    3.649s
------------------------------------
Enter fullscreen mode Exit fullscreen mode

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>)
        .................
        .................
Enter fullscreen mode Exit fullscreen mode
async Article's
30 articles in total
Favicon
This Small Python Script Improved Understanding of Low-Level Programming
Favicon
Async,Await Promise
Favicon
Async Vs Sync, which is most preferrable?
Favicon
Async/Await: Task.WhenAll + Exceptions = Dor de Cabeça!
Favicon
Everything You Need to Know About JavaScript Promises and How They Work
Favicon
Asynchronous Python
Favicon
Building pipelines with IAsyncEnumerable in .NET
Favicon
Unleash the Power of FastAPI: Async vs Blocking I/O
Favicon
Total Madness #2: Async Locks
Favicon
Don't use 'BuildContext's across async gaps.
Favicon
Integration Digest: May 2024
Favicon
Total Madness #1: Async/Await
Favicon
Forcing Angular SSR to Wait in 2024
Favicon
Using Async in Ruby on Rails for CSV export
Favicon
Mastering Async Await in JavaScript for Asynchronous Programming
Favicon
PHP HyperF + MariaDB -> Async / Parallel
Favicon
Async/await and SwiftUI
Favicon
🕒 Task vs Promise: Chaining
Favicon
🕒 Task vs Promise: Encadenación
Favicon
New custom blocks for Analytics Builder (async comms, downsampling and complex measurements)
Favicon
Concurrent-ruby (async) S3 files download
Favicon
Ruby class pattern to work with API requests with built-in async approach
Favicon
How to use ActionCable with async requests in a Ruby on Rails web app
Favicon
Introducing EventSail: A Python Library for Event-driven Programming
Favicon
Enhancing Asynchronous Data Fetching in Umbraco v14 with Lit Async Directives
Favicon
API simples que gera arquivos de forma assíncrona, com Java e Spring? Aqui tem!
Favicon
Async Axiom logging
Favicon
Rust: Actix-web -- Async Functions as Middlewares
Favicon
Streamlining Asynchronous Tasks in Django with Django Tasks Scheduler
Favicon
JavaScript async call analysis

Featured ones: