Cookie Consent by Free Privacy Policy Generator ๐Ÿ“Œ Concurrency in Node.js (Child Processes vs Worker Threads)

๐Ÿ  Team IT Security News

TSecurity.de ist eine Online-Plattform, die sich auf die Bereitstellung von Informationen,alle 15 Minuten neuste Nachrichten, Bildungsressourcen und Dienstleistungen rund um das Thema IT-Sicherheit spezialisiert hat.
Ob es sich um aktuelle Nachrichten, Fachartikel, Blogbeitrรคge, Webinare, Tutorials, oder Tipps & Tricks handelt, TSecurity.de bietet seinen Nutzern einen umfassenden รœberblick รผber die wichtigsten Aspekte der IT-Sicherheit in einer sich stรคndig verรคndernden digitalen Welt.

16.12.2023 - TIP: Wer den Cookie Consent Banner akzeptiert, kann z.B. von Englisch nach Deutsch รผbersetzen, erst Englisch auswรคhlen dann wieder Deutsch!

Google Android Playstore Download Button fรผr Team IT Security



๐Ÿ“š Concurrency in Node.js (Child Processes vs Worker Threads)


๐Ÿ’ก Newskategorie: Programmierung
๐Ÿ”— Quelle: dev.to

In this article, we'll explore how to leverage the power of child processes and worker threads to overcome the single-threaded limitation of Node.js, optimizing your applications for performance. Whether you're battling with heavy computations or managing numerous I/O operations, this article will provide you with practical insights and code examples to master concurrency in Node.js. Letโ€™s get started!

As a JavaScript runtime, Node.js is single-threaded by nature. This means that by default, all your JavaScript code in a Node.js application runs in a single sequence or thread. While this model simplifies many aspects of coding โ€” for example, you don't need to worry about complex synchronization issues common in multi-threaded environments โ€” it also means that your application can process only one operation at a time. This is generally not an issue for I/O bound work, like network requests or file system tasks, because Node.js uses a non-blocking I/O handling system and can offload these operations, allowing the single thread to do other work while waiting for the I/O operation to complete. However, for CPU-bound tasks โ€” those involving heavy computation โ€” the single-threaded nature can become a bottleneck. This is where techniques like asynchronous programming, worker threads, and child processes come into play, allowing for more efficient utilization of system resources and enhanced application performance.

While worker threads and child processes are alike in function โ€” offering ways to handle tasks in parallel to the main execution thread โ€” their applications vary significantly. Imagine a chocolate factory, the entire factory is a process with a building, machinery, raw materials, and workers. In computer terms, a process has its own memory space and resources allocated by the operating system. Within this factory, there are several assembly lines, each managed by a worker. These assembly lines are like threads, operating within the process (the factory) and sharing their resources (like raw materials and machinery); each thread (assembly line) can also work independently of the others.

Now, suppose the factory decides to make a new type of chocolate that requires a completely different set of machinery and raw materials. It might make sense to set up a new factory for this purpose. This new factory is like a child process. It's a completely separate process with dedicated resources, but it was spawned by the original process (the parent factory).

In computer science, threads and processes are fundamental units of execution. Using worker threads and spawning child processes can help speed up your code, but they also add complexity and can introduce new classes of bugs, so they should be used judiciously. In Node.js, the child_process and the worker_threads modules are used to spawn child processes and create worker threads respectively.

Letโ€™s consider how these modules work.

child_process

The child_process module allows us access to operating system features by executing commands within a child process. The child_process module provides various methods such as fork(), spawn(), exec(), execFile(), and their synchronous counterparts for different use cases.
Note: The examples in this article are Linux-based. For Windows, please replace the commands with their Windows equivalents.

spawn()

The spawn() method is the foundation of the child_process module, and it is essential for creating new processes to execute system commands. It is asynchronous by design, allowing the primary program to run concurrently without waiting for the child process to complete. The spawnSync() method provides equivalent functionality in a synchronous manner that blocks the event loop until the spawned process either exits or is terminated.

const { spawn } = require('child_process');
const child = spawn('ls', ['-lh', '/usr']);

child.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

Pipes for stdin, stdout, and stderr are established between the parent Node.js process and the spawned subprocess. These data streams allow us to manage the arguments provided to the underlying OS commands as well as the output of the operations. The child_process module allows the output of one process to be used as the input of another.

const { spawn } = require('child_process');
const grep = spawn('grep', ['ssh']);
const ps = spawn('ps', ['aux']);

ps.stdout.pipe(grep.stdin);
grep.stdout.on('data', (data) => {
  console.log(data.toString());
});
exec() and execFile()

exec() and execFile() methods allow for command execution with and without a shell, respectively. The exec() method spawns a shell and runs a command within that shell, passing the stdout and stderr to a callback function when complete. The exec() method is especially powerful, allowing numerous commands to be executed in a shell, but it must be used with caution due to security issues such as the potential of command injection attacks.

const { exec } = require('child_process');
exec('ls -lh /usr', (error, stdout, stderr) => {
  console.log(`stdout: ${stdout}`);
});

The synchronous counterparts for the exec and execFile methods are execSync() and execFileSync() respectively

fork()

The fork() method is used for spawning new Node.js processes. It creates a separate V8 instance, allowing JavaScript files to run in separate processes, and facilitating direct communication between the parent and child.

const { fork } = require('child_process');
const child = fork('child.js');

child.on('message', (message) => {
  console.log('Message from child:', message); // prints โ€˜helloโ€™
});

In child.js, messages can be sent to the parent process

process.send('hello')
Communication and Buffer Limits in Child Processes

Communication between parent and child processes is facilitated through Inter-Process Communication (IPC) channels. These channels allow messages to be sent between the parent and child, enabling data exchange and coordination for various tasks. Buffer limits play a crucial role in managing the data flow between parent and child processes. Exceeding these limits can lead to truncated data or failure in child processes. Adjusting parameters like maxBuffer helps in customizing these limits based on the applicationโ€™s needs.

exec('ls -lh /usr', { maxBuffer: 1024 * 1024 }, (error, stdout, stderr) => {
  console.log(`stdout: ${stdout}`);
});

worker_threads

The worker_threads module, introduced in Node.js v10.5.0, allows JavaScript code to be executed in parallel threads. This is especially useful for CPU-intensive tasks, as it improves program performance by allowing numerous threads to execute concurrently.

Unlike the child_process module, worker_threads can share memory. This shared memory capability allows for faster communication as data can be directly written and read from the buffer.

Hereโ€™s how you can create a simple worker thread:

const { Worker, isMainThread, parentPort } = require('worker_threads');

if (isMainThread) {
  const worker = new Worker(__filename);
  worker.once('message', (message) => {
    console.log(message); // Prints 'Worker thread: Hello!'
  });
} else {
  parentPort.postMessage('Worker thread: Hello!');
}

In the above example, we're creating a new worker thread and setting up message passing between the main thread and the worker.

Worker Pools

Creating a worker incurs some overhead. For better efficiency, especially in high-load situations, using worker pools could prove useful. A worker pool pre-allocates worker threads, allowing them to be reused, avoiding the cost of recreating them and thus improving performance and resource utilization.

Imagine you have a large dataset that needs to be processed. To process each data point independently using workers, first create a worker file containing the code to be executed by each worker. Letโ€™s call this file worker.js.

const { parentPort } = require('worker_threads');

parentPort.on('message', (data) => {
  // Simulating a CPU-intensive task
  let result = 0;
  for (let i = 0; i < 1e7; i++) {
    result += i;
  }

  // Sending the result back to the main thread
  parentPort.postMessage(result);
});

Worker pools can then be implemented in the main file:

// main.js
const { Worker } = require('worker_threads');

const poolSize = 5;

// Create a worker pool
const workers = [];
for (let i = 0; I < poolSize; i++) {
  workers.push(new Worker('./worker.js'));
}

// Function to get an idle worker
function getWorker() {
  return workers.find(worker => worker.isIdle);
}

Tasks can then be assigned to the workers and the results handled

// main.js
...
function processDataset(dataset) {
  dataset.forEach(data => {
    const worker = getWorker();
    if (worker) {
      worker.isIdle = false;
      worker.once('message', (result) => {
        worker.isIdle = true;
        console.log(`Result: ${result}`);
      });
      worker.postMessage(data);
    }
  });
}

const dataset = new Array(100).fill(null);
processDataset(dataset);

Now that you understand how these modules work, it's important to understand when NOT to use them. Despite their powerful capabilities, these modules should not be used for every task in your application. Worker threads, though ideal for CPU-bound tasks, can add unnecessary overhead for I/O-bound tasks, which are already efficiently handled by Node.js. Similarly, spawning child processes indiscriminately can lead to high memory consumption and system resource exhaustion, as each process carries a significant overhead in terms of system resources. In fact, for many web applications, the default single-threaded, event-driven model of Node.js is more than sufficient.

Furthermore, remember that since all threads of a process share the same heap, you will have to manage data access carefully to avoid race conditions. A race condition occurs when two or more threads can access shared data and try to change it at the same time. This can lead to unpredictable results as one thread may be modifying the data while another is trying to read it. Similarly, while child processes don't share the same heap, they still communicate with the parent process via Inter-Process Communication (IPC), and improper synchronization or mishandling of this communication can also lead to data inconsistencies or race conditions. Therefore, when utilizing these parallelism tools in Node.js, always ensure that shared resources are adequately synchronized, and carefully consider thread-safe strategies to prevent potential data corruption or unexpected application behaviors.

Thatโ€™s all for now! The article Node.js: Beyond the Basics provides a wealth of helpful insights and information to help you understand the non-blocking, event-driven architecture which Node.js is built with.

...



๐Ÿ“Œ Concurrency in Node.js (Child Processes vs Worker Threads)


๐Ÿ“ˆ 82.61 Punkte

๐Ÿ“Œ Node.js Worker Threads Vs. Child Processes: Which one should you use?


๐Ÿ“ˆ 63.67 Punkte

๐Ÿ“Œ Threads v Processes. Is everything a process? Do threads exist or is it just lingo enforced by pThreads?


๐Ÿ“ˆ 40.74 Punkte

๐Ÿ“Œ Concurrency Made Easy (Practical Tips For Effective Concurrency In Go)


๐Ÿ“ˆ 37.87 Punkte

๐Ÿ“Œ Concurrency Made Easy (Practical Tips For Effective Concurrency In Go)


๐Ÿ“ˆ 37.87 Punkte

๐Ÿ“Œ Maximizing the Power of Child Processes in Node.js: Real-world Examples


๐Ÿ“ˆ 35.87 Punkte

๐Ÿ“Œ Effortlessly Tame Concurrency in Golang: A Deep Dive into Worker Pools


๐Ÿ“ˆ 33.56 Punkte

๐Ÿ“Œ Modern C++ - Parallelismus und Concurrency #1 - Threads erstellen


๐Ÿ“ˆ 32.11 Punkte

๐Ÿ“Œ Exploring Lightweight Concurrency With Virtual Threads: A Developer-Agnostic Perspective


๐Ÿ“ˆ 32.11 Punkte

๐Ÿ“Œ Taming the Virtual Threads: Embracing Concurrency With Pitfall Avoidance


๐Ÿ“ˆ 32.11 Punkte

๐Ÿ“Œ Concurrency in golang with goroutines, threads and process.


๐Ÿ“ˆ 32.11 Punkte

๐Ÿ“Œ Kubernetest (on-prem) master node and worker node associations.


๐Ÿ“ˆ 31.19 Punkte

๐Ÿ“Œ After Amazon Increases Worker Wages, Whole Foods Responds By Cutting Worker Hours


๐Ÿ“ˆ 29.25 Punkte

๐Ÿ“Œ Web Extract Worker, a service with text-to-image worker AI models!


๐Ÿ“ˆ 29.25 Punkte

๐Ÿ“Œ Performance metrics from processes / top 10 processes of timeframe


๐Ÿ“ˆ 28.77 Punkte

๐Ÿ“Œ Microsoft Worker Arrested for Child Pornography After the Company Turned Him In


๐Ÿ“ˆ 27.83 Punkte

๐Ÿ“Œ Microsoft Worker Arrested for Child Pornography After the Company Turned Him In


๐Ÿ“ˆ 27.83 Punkte

๐Ÿ“Œ Worker Threads in JavaScript for Parallel Processing


๐Ÿ“ˆ 27.8 Punkte

๐Ÿ“Œ lucid - A simple mock-application for programs that work with child processes


๐Ÿ“ˆ 27.59 Punkte

๐Ÿ“Œ [TIL] Are threads same as processes in Linux?


๐Ÿ“ˆ 27.56 Punkte

๐Ÿ“Œ Why did Linus Torvalds lump threads and processes together?


๐Ÿ“ˆ 27.56 Punkte

๐Ÿ“Œ Where can I read about how processes and threads work in linux?


๐Ÿ“ˆ 27.56 Punkte

๐Ÿ“Œ 30,000 QPS Per Node: How We Increased Database Query Concurrency by 20 Times


๐Ÿ“ˆ 27.22 Punkte

๐Ÿ“Œ 330,000 QPS Per Node: How We Increase Database Query Concurrency by 20 Times


๐Ÿ“ˆ 27.22 Punkte

๐Ÿ“Œ DIVING INTO THE NODE.JS EVENT LOOP AND CONCURRENCY MODEL


๐Ÿ“ˆ 27.22 Punkte

๐Ÿ“Œ VB2019 preview: Problem child: common patterns in malicious parent-child relationships


๐Ÿ“ˆ 26.41 Punkte

๐Ÿ“Œ Kernel threads v User threads. Do they communicate via IPC for the sake of executing system calls?


๐Ÿ“ˆ 26.35 Punkte

๐Ÿ“Œ Cloud Foundry Container Runtime up to 0.27.x K8s Worker Node Deployment Credentials information disclosure


๐Ÿ“ˆ 22.91 Punkte

๐Ÿ“Œ Cloud Foundry Container Runtime up to 0.27.x K8s Worker Node Deployment Credentials information disclosure


๐Ÿ“ˆ 22.91 Punkte

๐Ÿ“Œ TSMC Accuses GlobalFoundries of Infringing 25 Patents For Node Processes


๐Ÿ“ˆ 22.67 Punkte

๐Ÿ“Œ Node enables companies to build AI into their applications, products, and business processes


๐Ÿ“ˆ 22.67 Punkte

๐Ÿ“Œ traceroute Package up to 1.0.0 on Node.js Child.exec host os command injection


๐Ÿ“ˆ 21.49 Punkte

๐Ÿ“Œ Rust Concurrency Explained


๐Ÿ“ˆ 18.93 Punkte

๐Ÿ“Œ Concurrency Patterns In Go


๐Ÿ“ˆ 18.93 Punkte











matomo