Difference between sequential and parallel execution in Node.js
Node.js is a JavaScript runtime environment that allows JavaScript code execution on the server side. It allows non-blocking, event-driven, and highly scalable applications, vastly used for building real-time applications. Node.js offers various execution models with practical usage. Node.js supports non-blocking operations, which means asynchronous programming, allowing several operations to be carried out simultaneously without blocking the other operations.
In this example, we’ll talk about the difference between two execution models of JavaScript: parallel and sequential execution.
Sequential execution
This type of execution has a queue of operations to be carried out one after another. One task has to be completed without moving on to the next task. The event loop processes only one task at a time, ensuring the second operation doesn't begin until the current task finishes. Sequential execution plays an important role in executing those functions where the order of execution matters in the overall execution.
The execution can have a blocking nature, especially for tasks requiring high processing time like I/O operations, database queries, and network requests. The blocking nature causes the event loop to pause, causing delayed responsiveness.
The possible use cases of sequential execution are synchronous coding problems where each task depends on the completion of the previous task and problems where dependencies exist between tasks.
Here’s a coding example to demonstrate the sequential execution of tasks.
//Sequential execution example
// Function to print status of task 1 after timeout
function task1(i) {
setTimeout(() => {
console.log("Executing task ",{i});
i = i + 1;
// call the next sequential task 2
task2(i);
},1000);
}
// Function to print status of task 2 after timeout
function task2(i) {
setTimeout(() => {
console.log("Executing task ",{i});
i = i + 1;
// call the next sequential task 3
task3(i)
},1000);
}
// Function to print status of task 3 after timeout
function task3(i) {
setTimeout(() => {
console.log("Executing task ",{i});
i = i + 1;
},1000);
}
//sequentially calling task 1
console.log("Sequential Execution: ");
task1(1);In the code:
Lines 3,13,23: Define function
task1,task2, andtask3with an iteratorithat indicates the tasks under execution.Lines 4,14, 24: Definition of time-delayed task using
setTimeout.Lines 5, 15, 25: Logging of execution of the task and its value, i.e.,
i.Line 6, 16, 26: Incrementation of variable
ithat represents the task under execution.Line 8: Initiation of
task2withivalue 2.Line 18: Initiation of
task3withivalue 3.Line 32: Initiation of
task1withivalue 1.
While sequential execution seems simple and deterministic in task handling, it may lead to performance bottlenecks in the case of long-running operations.
Parallel execution
Parallel execution makes use of the cores and processors. Parallel execution divides tasks into multiple portions and executes each of them simultaneously on different processors. This type of execution helps avoid bottlenecks created in sequential execution.
In parallel execution, tasks are carried out concurrently and do not depend on or wait for other tasks. Each task executes independently, and the events loop is available to be used by other tasks. No task blocks the execution of other tasks. This type of execution is particularly beneficial in executing applications with CPU-bound tasks. The tasks can be high data processing or solving complex mathematical problems.
Parallel execution is beneficial in performing asynchronous operations, parallelizing tasks and in applications where server executes multiple tasks simultaneously.
Here’s a coding example to demonstrate the parallel execution of tasks. It makes use of the Promise to parallelize tasks.
// Parallel Execution Example
// Function to print Task 1 status after timeout
function task1(i) {
return new Promise((resolve) => {
setTimeout(() => {
console.log("Task",{i} ,"completed");
resolve();
}, 1000);
});
}
// Function to print Task 2 status after timeout
function task2(i) {
return new Promise((resolve) => {
setTimeout(() => {
console.log("Task",{i} ,"completed");
resolve();
}, 1000);
});
}
// Function to print Task 3 status after timeout
function task3(i) {
return new Promise((resolve) => {
setTimeout(() => {
console.log("Task",{i} ,"completed");
resolve();
}, 1000);
});
}
console.log("\nParallel Execution:");
// Asynchronous function to execute tasks in parallel
async function executeParallelTasks() {
// Wait for all tasks to be complete
await Promise.all([task1(1), task2(2), task3(3)]);
console.log("Parallel execution complete");
}
executeParallelTasks();In the code:
Lines 3,13,23: Define function
task1,task2, andtask3withiindicating the tasks under execution.idon’t indicate iteration, as all tasks are executing concurrently.Lines 4,14,24: Initiate
Promisefunction. ThePromisefunction helps create an asynchronous operation by assigning a value to thePromiseat the end of function's execution.Lines 5,15,25: Definition of time-delayed task using
setTimeout.Lines 6,16, 26: Logging of execution of the task and its value, i.e.,
i.Lines 7,17,27:
resolvefunction called indicating completion of thePromisefunction.Line 34: Initiation of asynchronous function using
asyncLine 36:
awaitwaits forPromise.allto return thePromiseof all the parallel tasks.Line 40: Initiation of the parallel processes.
Parallel execution makes the processing time smaller and manages the tasks efficiently.
Key differences
Let’s conclude the key differences between sequential and parallel execution of tasks. It is important to note that while each execution type has its specific practical usage, misusing the execution can hinder the performance of the operations. Here is a conclusive table to differentiate between the two.
Properties | Sequential execution | Parallel execution |
Sync vs. async | Synchronous | Asynchronous |
Execution order | In queue | Simultaneous |
Blocking vs. non-blocking | Blocking | Non-blocking |
Performance in CPU-bound operations | Slower | Faster |
Different type of operation needs a different type of execution. Identifying the type of operation can help with the efficiency in which the operation can be carried out.
Free Resources