Developers use Node.js, a popular open-source cross-platform environment, to create server-side applications for different platforms. This environment comes with a single-threaded event loop for the application, which enables the CPU-bound operations to cause the parent thread of the system to block and create delays. To overcome this issue, Node.js has a worker threads module that addresses this problem perfectly by offering a mechanism that helps the developers to run different threads in parallel.
This blog will teach us all about multiple threads, their usage in Node.js, and how developers can implement multiple threading in a Node.js application. This will not only prevent CPU-intensive tasks from blocking the main thread but also help developers synchronize threads and execute them. We will also go through the architecture of multithreading.
1. When to Use Multithreading in Node.js?
One widely used JavaScript runtime environment is Node.js. As it is a single-threaded programming language, it executes its code in a single thread, which means that the code written using Node.js can only do one task at a time. But at the same time, Node.js itself is multithreaded which means it has the capability to offer hidden threads through the libuv library. This library in Node.js handles I/O operations like reading files from a network or a disk. By using this file and the hidden threads, Node.js can offer asynchronous methods that enable the JavaScript code to make I/O requests without blocking the main thread. These hidden threads cannot offload CPU-intensive tasks like image resizing, complex calculations, or video compression. The reason is that JavaScript, being a single-threaded language, will block the main thread when running CPU-intensive operations, preventing other JavaScript code from executing until the task is completed.
To overcome this issue, Node.js introduced the worker-threads module. Worker threads provide a workaround to create separate threads and execute multiple JavaScript tasks with it at the same time. In this case, once a thread finishes a task, a message is sent to the main thread that contains the result of the operation which can be used for other tasks. The new worker instance of Node.js enables the developers to use worker threads in any type of CPU-bound task without blocking the main thread of the application. Besides this, the Node.js developers can easily divide and distribute a task to various workers to optimize it.
In Node.js, you can clearly see that you can use multithreading when the application needs to execute various tasks without impacting CPU-intensive JavaScript operations and without blocking the main thread of the system.
2. Implementation of Multithreading in Node.js
Here is the process that every Node.js developer must follow while implementing the multithreading approach to their software development process. To know more about it, let’s go through the implementation process of worker threads.
Here is the problem that companies are facing while going through multiple threads implementations.
2.1 Implementation – Problem Statement
In Node.js development services, many places require an active worker thread. Here, we will go through an example that illustrates how one can use the worker threads in Node.js. For instance, when a web app developer is creating a web application that has a lot of stock videos, the need for a worker thread arises. The application will add a watermark, which is the logo of the application for copyright issues, to the video when the user wants to upload videos in such applications. By adding the watermark sign, the system enables the users to implement the video with the use of ffmpeg. However, creating the application in Node.js poses a main problem because the system is CPU intensive. This means that implementing the watermark directly in the app will block the application’s threads, eventually affecting the performance of the Node.js application.
2.2 Solution
Implementing worker threads is essential to enable Node.js applications to remain unaffected by CPU-intensive JavaScript operations and to ensure the smooth processing of the app. So here, let’s see what the implementation process is and how it works.
The very first step like always is to create a directory and initialize the Node.js project by using
npm init --yes |
Now, after the creation and initialization of the project, the next step is to install the dependencies. For that, the command, npm i express body-parser ffmpeg hbs multer is run. The meaning of this command is as follows –
- express – In the above command express means that Node.js Framework will handle the request and response of it.
- body-parser – Here, body-parser means that the framework will handle the request post-body.
- ffmpeg – In the above command, we use the ffmpeg library to handle the addition of a watermark to the uploaded videos.
- hbs – The command specified for installing the dependencies identifies hbs or handlebars as the template engine that can assist in rendering views in express applications.
- multer – And multer is used as it has the capability to handle the file upload.
The next step after installing the dependencies in the Node.js application is to use babel to use ES6. Here, babel compile ES6 to JavaScript. Below is the command that will specify the usage of babel.
npm i --save-dev @babel/cli @babel/core @babel/node @babel/preset-env dotenv nodemon |
Now, here we will create a file called .babelrc and then add the following code to it.
{ "presets": [ [ "@babel/preset-env", { "targets": { "node": true } } ] ] } |
After adding the above code in the .babelrc file, now let’s create a view directory, and create a file index.hbs inside that directory, and then add the following code inside that file.
<title>Add Video Watermark</title> <h1>Video Watermark</h1> {{# if error }} <div class="ui negative message"> <i class="close icon"></i> <div class="header">{{error}}</div> </div> {{/if}} <div class="field"> <label>Upload Video</label> </div> <button class="ui button">Add</button> |
The above code has the HTML code that enables the form to take a video file as input. After submitting the form, the express file can handle the route of the video file to retrieve the data. For this, here is the code.
import express from "express"; import * as bodyParser from "body-parser"; import * as path from "path"; import multer from "multer"; require("dotenv").config(); // add date-time and any random number to file-name const random = Math.floor(Math.random() * Math.floor(9999)); const storage = multer.diskStorage({ destination: "./uploads/", filename: (req, file, cb) => { cb( null, file.fieldname + "-" + Date.now() + random + path.extname(file.originalname) ); }, }); // upload single file using multer const uploadVideo = multer({ dest: "uploads", storage: storage }); const app = express(); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.set("views", path.join(__dirname, "views")); app.set("view engine", "hbs"); // end-point to add file app.post("/upload-video", uploadVideo.single("video"), (req, res) => { console.log('Uploaded File:', req.file); }); app.get("/", (req, res) => { res.render("index"); }); const port = process.env.PORT || 3000; app.listen(port, () => { console.log(`Server is running on PORT number ${port}`); }); |
In the above code, we have set a handlebar template engine with the multer in the express application. And after doing so we have got two routes that are responsible to handle the default index page of the application and upload the video URL. Because of this, uploading file data in the /upload-video URL is possible along with processing the video. After completing all this, we implement the worker threads, providing a multithreading Node.js application.
3. Multi-Thread Architecture
Multithreading means a single CPU core handling various threads’ execution. It comes with the ability to make a program or an operating system process tasks for more than one user simultaneously, without blocking any task . By using multi-thread architecture the developers can offer execution of multiple threads concurrently. One of the best examples of this architecture is a word processor. While the user is typing in it, the system uses multiple threads to display the document, check the grammar, and generate a PDF version of the document.
4. Conclusion
This blog highlights the usefulness of employing multi-thread architecture in Node.js applications, as it can enable the application to complete I/O tasks more efficiently without affecting the main process. The reason behind it is that in Node.js there are two threads, the event loop known as the main thread, and the worker pool known as the thread pool. Here, the libuv library automatically creates and executes the worker pool, so developers can manage the main thread but have no control over the worker pool. However, using multithreading can enable developers to handle it and also carry out various thread executions without affecting the main thread.
5. FAQ
Is it possible to multithread Node.js?
NodeJS itself is a multithreaded technology that offers hidden threads via the library named libuv that helps manage I/O operations like reading files from network requests.
What is the difference between multithreading and multiprocessing in node js?
The NodeJS app development ecosystem recognizes multiprocessing as a system that provides more than one or two processors, used to augment the computing speed of the system by adding CPUs. Conversely, multithreading is a system that encompasses multiple threads created within a process to enhance the computing speed of the entire system.
How node js is fast if it is single threaded?
Though NodeJS is a single-threaded technology it is able to process all the tasks faster than any other JavaScript technologies because single thread reduces the overhead of thread communication which eventually helps in using the same shared memory without any communication.
Comments
Leave a message...