Two techniques to prevent blocking the Event Loop when handling CPU-intensive tasks

Two techniques to prevent blocking the Event Loop when handling CPU-intensive tasks

Daily short news for you
  • Thank you to threads.net from Meta for being the inspiration behind this section on my blog. Initially, I was a bit skeptical about whether creating short posts like this would attract users, whether anyone would come back to read day after day, or if it would all just be like building sandcastles by the sea. As I have often mentioned, creating a feature is not difficult, but how to operate it effectively is what truly matters.

    Now, time has proven everything. The Short Posts section consistently ranks in the top 5 most visited pages of the day/week/month. This means that readers have developed a habit of returning more often. How can I be so sure? Because this section is almost completely unoptimized for SEO on search engines like Google.

    Let me take you back a bit. In the beginning, I was very diligent in posting on threads.net in the hope of attracting many followers, so that I could subtly introduce them to become users of my blog. However, as time went on, I increasingly felt "exhausted" because the Threads algorithm became less and less aligned with my direction. In other words, the content created was not popular.

    For example, my posts often lean towards sharing information, news, or personal experiences drawn from learning or doing something. It seems that such posts are not highly regarded and often get buried after just over... 100 views. Hmm... Could the problem be me? Knowing this, why not change the content to be more suitable for the platform?

    I have observed Threads, and the content that spreads the most easily often contains controversial elements or a prejudice about something, sometimes it’s simply stating something "naively" that they know will definitely get interactions. However, I almost do not like directing users towards this kind of content. People might call me stubborn, and I accept that. Everyone has different content directions and audiences; the choice is theirs.

    So, from then on, I mainly write here. Only occasionally, if I find something very interesting, do I go on Threads to "show off." Here, people still come to read daily; no matter who you are, I am sure that you can recognize the message I want to convey through each post. At the very least, we share a common direction regarding content. Sometimes, the scariest thing is not that no one reads what you write, but that they read it and then forget it in an instant. Quantity is important, but quality is what brings us closer together.

    Thank you all 🤓

    » Read more
  • Zed is probably the most user-centric developer community on the planet. Recently, they added an option to disable all AI features in Zed. While many others are looking to integrate deeper and do more with AI Agents. Truly a bold move 🤔

    You Can Now Disable All AI Features in Zed

    » Read more
  • Today I have tried to walk a full 8k steps in one session to show you all. As expected, the time spent walking reached over 1 hour and the distance was around 6km 🤓

    Oh, in a few days it will be the end of the month, which means it will also mark one month since I started the habit of walking every day with the goal of 8k steps. At the beginning of next month, I will summarize and see how it goes.

    » Read more

Issue

Complex calculations can often cause the Event Loop to become blocked, resulting in unresponsiveness of the server until the computation is complete.

Does this mean Node.js struggles with such calculations? In today's article, I will present two techniques to address this issue.

Partitioning

Also known as "chunking," this technique is based on the principle of dividing the calculation into smaller parts to ensure the interleaving of the Event Loop.

For example, consider an average calculation of numbers from 1 to n with a complexity of O(n):

for (let i = 0; i < n; i++)
  sum += i;
let avg = sum / n;
console.log('avg: ' + avg);

The complexity and CPU usage increases as n increases. However, by applying the Partitioning technique, the calculation can be divided into n asynchronous steps with a constant performance cost of O(1):

function asyncAvg(n, avgCB) {
  var sum = 0;
  function help(i, cb) {
    sum += i;
    if (i == n) {
      cb(sum);
      return;
    }

    setImmediate(help.bind(null, i+1, cb));
  }

  help(1, function(sum){
      var avg = sum/n;
      avgCB(avg);
  });
}

asyncAvg(n, function(avg){
  console.log('avg: ' + avg);
});

Partitioning utilizes setImmediate to perform each step of the loop asynchronously, ensuring that the Event Loop is not blocked since setImmediate is executed during the "Check" phase. To learn more, I recommend reading the article Understanding the Event Loop in Node.js (in Vietnamese). In simple terms, calculations are performed on each iteration of the Event Loop.

Offloading

If your task is more complex, Partitioning might not be sufficient. The Event Loop is responsible for ordering the execution of tasks, not directly executing them. To take advantage of multi-core processors, offload the tasks from the Event Loop.

There are two ways to apply Offloading:

To learn more about Worker Thread implementations, you can refer to the article What are Worker threads? Do you know when to use Worker threads in node.js? (in Vietnamese).

Conclusion

For simple tasks, such as iterating over elements of an arbitrarily long array, Partitioning can be a good choice. If your computational logic is more complex, Offloading is a better approach.

The Offloading technique incurs some overhead due to the communication between the serialized objects of the Event Loop and the Worker Pool. However, it can utilize the CPU's multiple cores.

However, if your server primarily performs heavy CPU computations, you should consider whether Node.js is the best fit. Node.js excels with asynchronous I/O tasks but may not be the optimal choice for CPU-intensive tasks.

References:

Premium
Hello

5 profound lessons

Every product comes with stories. The success of others is an inspiration for many to follow. 5 lessons learned have changed me forever. How about you? Click now!

Every product comes with stories. The success of others is an inspiration for many to follow. 5 lessons learned have changed me forever. How about you? Click now!

View all

Subscribe to receive new article notifications

or
* The summary newsletter is sent every 1-2 weeks, cancel anytime.

Comments (1)

Leave a comment...
Avatar
Gin Na3 years ago

Phép tính đc thực hiện trên mỗi lần lặp là sao ạ?

Reply
Avatar
Xuân Hoài Tống3 years ago

Bạn đọc lại bài viết https://2coffee.dev/bai-viet/tim-hieu-ve-vong-lap-su-kien-event-loop-trong-nodejs-8 này để biết thêm các event loop hoạt động nhé

Avatar
Gin Na3 years ago

@gif [3o6Zt6KHxJTbXCnSvu] Cảm ơn ad