Hướng dẫn nodejs worker thread example - ví dụ về luồng công nhân nodejs

Trong Node.js, các chủ đề công nhân có ích khi thực hiện các tác vụ JavaScript lớn. Công nhân làm cho việc chạy mã JavaScript đơn giản bằng các luồng, làm cho nó nhanh hơn và hiệu quả hơn đáng kể. Chúng ta có thể hoàn thành các công việc khó khăn mà không làm gián đoạn chủ đề chính. Chủ đề công nhân không có sẵn trong các phiên bản nút trước đó. & NBSP;

Nó cũng chịu trách nhiệm chuyển các trường hợp ArrayBuffer để xử lý các hoạt động chuyên sâu CPU.

Các chủ đề của Node.js Worker đã được chứng minh là giải pháp lớn nhất cho hiệu suất CPU vì các tính năng sau:

  • Nó chạy một quá trình duy nhất với nhiều luồng.
  • Chạy phiên bản động cơ JS đơn cho mỗi luồng.
  • Thực hiện một vòng lặp sự kiện cho mỗi luồng.
  • Thực thi cá thể một nút đơn. Mỗi luồng.

Để bắt đầu, chúng tôi phải cập nhật Node.js của chúng tôi lên phiên bản mới hơn. & NBSP;

Lịch sử của các ứng dụng chuyên sâu CPU trong Node.js

Có một số cách để chạy các ứng dụng chuyên sâu CPU trong Node.js trước các luồng công nhân. Một số trong số chúng được đề cập ở đây:

  • Chạy các chương trình chuyên sâu CPU trong một quy trình trẻ em với mô-đun quy trình con.
  • Để thực hiện nhiều hành động sử dụng nhiều CPU trong nhiều quy trình, hãy sử dụng mô-đun cụm.
  • Sử dụng mô-đun của bên thứ ba như NAPA.JS từ Microsoft.

Tuy nhiên, không có lựa chọn thay thế nào được thực hiện rộng rãi do hạn chế về hiệu suất, tăng độ phức tạp, thiếu chấp nhận, không ổn định và tài liệu.

Sử dụng các luồng công nhân cho các hoạt động chuyên sâu CPU

Chủ đề công nhân là một giải pháp tuyệt vời cho vấn đề đồng thời của JavaScript; Nó không cung cấp các cơ sở đa luồng cho ngôn ngữ. Thay vào đó, phương pháp tiếp cận chủ đề công nhân cho phép các ứng dụng sử dụng một số công nhân JavaScript bị cô lập, với nút cung cấp giao tiếp giữa công nhân và nhân viên phụ huynh. Mỗi công nhân trong Node.js có phiên bản V8 và Vòng lặp sự kiện riêng. Công nhân, không giống như quá trình của trẻ em, có thể trao đổi bộ nhớ.

Example:

const {worker} = yêu cầu ('worker_threads')

const RunService = (WorkerData) => {

& nbsp; & nbsp; & nbsp; & nbsp; trả lại lời hứa mới ((giải quyết, từ chối) => {

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; ;

        })

    })

}

const chạy = async () => {

& nbsp; & nbsp; & nbsp; & nbsp; const result = Await RunService ('Xin chào Node.js'))

    console.log(result);

}

const chạy = async () => {

& nbsp; & nbsp; & nbsp; & nbsp; const result = Await RunService ('Xin chào Node.js'))

chạy (). Catch (err => console.error (err))

Thêm tệp này vào tệp WorkerExample.js.

Output:

const {workerData, ParentPort} = Yêu cầu ('worker_threads')

ParentPort.PostMessage ({Chào mừng: WorkerData})

{Chào mừng: 'Xin chào Node.js'}

Chúng tôi đã nhập công nhân từ các chủ đề công nhân trong tập lệnh chính của chúng tôi, sau đó chuyển dữ liệu (tên tệp) cho công nhân xử lý. Như đã thấy trong dịch vụ WorkerExample.js, bước tiếp theo là lắng nghe các sự kiện tin nhắn từ chuỗi công nhân. Ứng dụng chính của chúng tôi gửi WorkerData đến dịch vụ công nhân này, bao gồm một phương tiện để truyền dữ liệu đã xử lý trở lại thông qua ParentPort. Chúng tôi sử dụng postmessage () trên đối tượng này (ParentPort) để cung cấp dữ liệu đã xử lý.

Node.jsWorker

Chủ đề công nhân cũng cho phép chúng tôi chia sẻ bộ nhớ bằng cách sử dụng các đối tượng SharedArrayBuffer. Chuyển các đối tượng ArrayBuffer cũng có thể được sử dụng để chia sẻ bộ nhớ.

Làm thế nào để chủ đề công nhân hoạt động?

What Distinguishes Worker Threads

  • To pass starting data, WorkerData is used. An arbitrary JavaScript value containing a clone of the data supplied to the Worker function Object() { [native code] } of this thread. As if using postMessage, the data is cloned ().
  • MessagePort is a communication port that allows many threads to communicate with each other. It can be used to send structured data, memory regions, and other MessagePorts from one worker to another.
  • Atomics is a tool that allows you to run several processes at the same time, saving time and allowing you to use JavaScript to add conditional variables.
  • MessageChannel is an asynchronous, two-way communication channel that can be used to communicate between threads.

How Do Node.js Workers Run in Parallel?

A V8 isolate is a standalone Chrome V8 runtime instance with its own JS memory and microtask queue. This allows each Node.js worker to run its JavaScript code entirely independently of the other workers. The disadvantage is that the workers are unable to immediately access each other's heaps.

Crossing the JS/C++ Boundary

Using Node.js' APIs, the script is passed to V8. The JS code in the specified script is compiled by V8, and the assembly equivalent is returned. The produced assembly code is then run by Node.js using another V8 API. The code is compiled to assembly and copied to memory by the compiler.

To run the compiled code, it allocates a space on the memory, moves the code to the allocated space, and jumps to the memory space. Execution now starts from the compiled code at the jump. As a result, it has crossed a line. The code that is currently being run is JS code rather than C++ code. All of the pieces are now in place for assembly. When the compiled JS code is finished, it returns to the C++ code.  

The terms "C++ code" and "JS code" do not refer to the C++ or JS source code. It is the assembly code generated by the compiler from their source codes that is being executed to distinguish which assembly code is being executed.

Based on the above, we can split the worker setup process into two stages: 

  1. Initialization of the worker
  2. Running the worker

Initialization Step

  • The worker threads module in the Userland script is used to construct a worker instance.
  • The initialization script for Node's parent worker invokes C++ and produces an instance of an empty worker object. At this moment, the created worker is just a plain C++ object that hasn't begun yet.
  • When a C++ worker object is created, it assigns itself to a thread and generates a thread ID.
  • When the worker object is formed, the parent worker creates an empty initialization message channel.
  • The worker initialization script creates a public JS message channel. This is the message channel that the userland JS uses to send messages between the parent and the child worker.
  • The initialization metadata for the worker execution script is written to the IMC by the node parent worker initialization script, which calls into C++.

Running Step

The initialization process is now complete. The worker thread is then started by the worker initialization script, which calls into C++.

  • The worker is given a new V8 isolation to work with. A V8 isolate is a V8 runtime instance that runs on its own. The execution context of the worker thread is thus segregated from the rest of the application code.
  • libuv has been set up. This allows the worker thread to run its own event loop separate from the rest of the program.
  • The worker's execution script is performed, and the event loop for the worker is initiated.
  • Execution of workers: 
  1. The script uses C++ to access the IMC's initialization metadata.
  2. The worker execution script runs the file that will be used by the worker. Worker-simple in our case, is instance.js.

Getting the Best Out of Worker Threads

We now know how Node.js Worker Threads function. Understanding how they work can help us achieve the greatest results from worker threads. When creating more complex apps than worker-simple.js, we must keep in mind the following two primary worker thread considerations.

  • Even though worker threads are more lightweight than actual processes, spawning workers requires significant effort and might be costly if done frequently.
  • Using worker threads to parallelize I/O operations is not cost-effective because using Node.js native I/O techniques is relatively faster than establishing a worker thread from scratch solely to do that.

Worker Thread Pooling

In Node.js, worker thread pools is a collection of active worker threads that can be used to complete an incoming job. When a new task is received, it can be assigned to a worker who is available. Once the worker has completed the task, the result can be returned to the parent, and the worker is again available to accept new assignments. Thread pooling, when properly implemented, can dramatically increase speed by reducing the overhead of spawning new threads. It's also worth noting that establishing a high number of threads is inefficient because the number of parallel threads that can be properly run is always restricted by hardware.

Tăng cường sự nghiệp của bạn với tư cách là một nhà phát triển Stack trung bình với & NBSP; Nhà phát triển Web Stack Full - có nghĩa là chương trình của Stack Master. Ghi danh ngay!

Sự kết luận

Vào tháng 4 năm 2019, Node.js v12 đã được ra mắt. Các luồng công nhân, được bật theo mặc định trong phiên bản này, hiện đã được hỗ trợ (thay vì cần một cờ thời gian chạy tùy chọn). Không bao giờ dễ dàng hơn khi sử dụng một số lõi CPU trong các ứng dụng Node.js!

Khả năng này có thể được sử dụng bởi các ứng dụng Node.js có khối lượng công việc sử dụng nhiều CPU để giảm thời gian thực hiện. Điều này đặc biệt quan trọng đối với các chức năng của Node.js Serverless vì các nền tảng không có máy chủ dựa trên thời gian thực hiện. Sử dụng một số lõi CPU dẫn đến hiệu suất nâng cao cũng như giảm chi phí.

Công nhân (chủ đề) rất hữu ích cho việc thực hiện các hành động JavaScript đòi hỏi nhiều sức mạnh CPU. Chúng không hữu ích cho các nhiệm vụ đòi hỏi nhiều I/O. Các hoạt động I/O không đồng bộ được tích hợp vào Node.js hiệu quả hơn công nhân. Chủ đề công nhân, không giống như quá trình con hoặc cụm, có thể chia sẻ bộ nhớ. Họ đạt được điều này thông qua việc chia sẻ các trường hợp SharedArrayBuffer hoặc chuyển các đối tượng ArrayBuffer. Chúng tôi hy vọng rằng bài viết này có thể cung cấp cho bạn kiến ​​thức kỹ lưỡng về & nbsp; Node JS Worker It Các tính năng của nó và cách chúng tôi có thể sử dụng nó trong các dự án phát triển phần mềm của mình.

Nếu bạn quan tâm đến việc tìm hiểu thêm về NodeJS và các khái niệm liên quan khác, bạn có thể đăng ký khóa học chứng nhận phát triển web Full Stack Stack độc quyền và tăng tốc sự nghiệp của bạn như một nhà phát triển phần mềm. Chương trình bao gồm một loạt các khóa học phát triển phần mềm, từ các nguyên tắc cơ bản đến các chủ đề nâng cao. & NBSP;

SimpleLearn cũng cung cấp các khóa học kỹ năng trực tuyến miễn phí trong một số lĩnh vực, từ Khoa học dữ liệu và phân tích kinh doanh đến phát triển phần mềm, AI và học máy. Bạn có thể tham gia bất kỳ khóa học nào trong số này để nâng cấp kỹ năng của bạn và nâng cao sự nghiệp của bạn.