Chủ đề Nodejs

Nút. js là một trong những công nghệ được ưa thích nhất hiện có để xây dựng các ứng dụng web thời gian thực do tính chất không chặn, hướng sự kiện và đơn luồng của nó. Nút. js được xây dựng với mục đích phát triển các ứng dụng có thể xử lý hiệu quả các hoạt động chuyên sâu I/O

Tại sao chúng ta cần xử lý song song?

Một trong những thành phần quan trọng nhất trong kiến ​​trúc của Node là libuv. libuv là một thư viện dựa trên C++ giúp thực thi không đồng bộ các hoạt động dựa trên I/O theo cách không chặn. Nó cũng cung cấp một giao diện được gọi là Vòng lặp sự kiện, lấy mã được thực thi từ ngăn xếp cuộc gọi và thực thi nó. Do tính chất đơn luồng, Vòng lặp sự kiện chỉ thực hiện một việc tại một thời điểm

Khi Vòng lặp sự kiện gặp mã phải được thực thi không đồng bộ (e. g. , truy cập hệ thống tệp, thực hiện cuộc gọi mạng và các hoạt động I/O khác), thay vì tự thực thi mã, mã này ủy quyền mã đó cho một nhóm luồng và chuyển sang thực thi phần còn lại của chương trình. Sau đó, các luồng sẽ thực thi song song mã không đồng bộ và trả lại một sự kiện cho Vòng lặp sự kiện sau khi hoàn thành

Chủ đề Nodejs

Hành vi không đồng bộ không chặn này của Node. js cho các hoạt động I/O giúp tối đa hóa thông lượng và làm cho nó trở thành lựa chọn lý tưởng để xây dựng các ứng dụng chuyên sâu I/O

Tuy nhiên, không có hoa hồng nào mà không có gai. Kiến trúc tập trung vào I/O và bản chất đơn luồng của Event Loop cũng có nghĩa là Node. js không hoạt động hiệu quả với các hoạt động chuyên sâu của CPU

Không giống như các thao tác I/O, các thao tác dựa trên CPU được thực thi bởi chính Vòng lặp sự kiện và không được ủy quyền cho nhóm luồng để thực thi không đồng bộ. Do đó, đối với các hoạt động tốn thời gian của CPU, Vòng lặp sự kiện vẫn bị chiếm dụng và chương trình bị chặn thực hiện thêm

Vì vậy, điều này có nghĩa là Node. js là KHÔNG lớn khi nói đến việc phát triển các ứng dụng có hoạt động nặng của CPU?

Mặc dù nút. js được thiết kế chủ yếu cho các ứng dụng chuyên sâu I/O, nó cung cấp cho chúng tôi các khả năng bổ sung để xử lý hiệu quả các tác vụ đòi hỏi CPU. Và một trong những cách để làm như vậy là sử dụng Worker Threads

Chủ đề công nhân để giải cứu

Chuỗi công nhân giúp chúng tôi giảm tải các tác vụ chuyên sâu của CPU khỏi Vòng lặp sự kiện để được thực thi song song theo cách không chặn. Chuỗi công nhân chạy một đoạn mã theo chỉ dẫn của chuỗi mẹ tách biệt với chuỗi cha và các chuỗi công nhân khác. Mỗi luồng công nhân có môi trường V8 riêng biệt, vòng lặp sự kiện, hàng đợi sự kiện, v.v. Nhân viên và phụ huynh có thể giao tiếp với nhau thông qua kênh nhắn tin. Chuỗi công nhân cung cấp cho chúng tôi cách chạy nhiều luồng trong một quy trình

Ngoài việc giữ cho Vòng lặp sự kiện không tốn thời gian cho các hoạt động của CPU, chúng ta cũng có thể sử dụng một nhóm các chuỗi công nhân để phân chia và thực hiện song song các hoạt động nặng của CPU nhằm tăng hiệu suất của Nút của chúng ta. ứng dụng js

Để hiểu rõ hơn về lợi ích của Node. js, chúng ta hãy lấy một tác vụ sử dụng nhiều CPU đơn giản làm ví dụ và so sánh thời gian thực hiện của tác vụ với các tình huống khác nhau

Nhiệm vụ đang diễn ra

Giả sử chúng ta được cung cấp một thư mục có 1000 tệp JSON trong đó và chúng tôi được giao nhiệm vụ chuyển đổi từng tệp JSON thành tệp XML

Mỗi tệp JSON có một mảng gồm 1000 đối tượng, với mỗi đối tượng có 6 cặp khóa-giá trị như trong ví dụ bên dưới

{
  "id": 1,
  "first_name": "abc",
  "last_name": "xyz",
  "email": "[email protected]",
  "gender": "Male",
  "ip_address": "163.213.59.129"
}

Chương trình của chúng tôi sẽ đọc từng tệp JSON, phân tích cú pháp và chuyển đổi nó thành đầu ra XML

Đọc/ghi tệp là các hoạt động I/O và Nút. js sẽ xử lý chúng một cách không đồng bộ

Tuy nhiên, phân tích cú pháp JSON và chuyển đổi nó thành XML sẽ là một hoạt động đòi hỏi CPU vì chúng tôi có một số lượng lớn các đối tượng JSON lớn

kịch bản thực hiện

Ghi chú. Trong tất cả các trường hợp, thời gian đọc nội dung từ tệp JSON không được thêm vào thời gian thực hiện. Chúng tôi đã sử dụng chức năng để tính toán thời gian thực hiện. Để cân bằng lỗi, chúng tôi sẽ chạy mỗi kịch bản 5 lần và lấy thời gian trung bình làm thời gian thực hiện

Tình huống 1 - Thực thi đồng bộ không có luồng worker

Ở đây, chúng tôi phân tích cú pháp và chuyển đổi nội dung JSON theo cách đồng bộ mà không cần sử dụng worker thread

⏰ Thời gian thực hiện trung bình. 1036 mili giây

Kịch bản 2 - Thực thi không đồng bộ với một luồng công nhân

Ở đây, chúng tôi phân tích cú pháp và chuyển đổi nội dung JSON theo cách không đồng bộ bằng một luồng công nhân

Chúng tôi sẽ sử dụng mô-đun worker_threads tích hợp từ Node. js để quản lý Worker Threads

⏰ Thời gian thực hiện trung bình. 1146 mili giây

Trong trường hợp này, chúng tôi thấy thời gian thực hiện tăng nhẹ. Mặc dù hiện tại hoạt động yêu cầu CPU được chạy trên một luồng riêng biệt, công nhân cũng sẽ mất một khoảng thời gian tương tự để thực hiện hoạt động. Bản thân việc tạo một luồng công nhân mới là một hoạt động tốn kém và do đó chúng tôi thấy thời gian thực hiện tăng lên

Thực thi không đồng bộ một thao tác CPU trên một luồng đơn lẻ có thể có lợi nếu bạn có một số phần khác của chương trình có thể thực thi song song trong luồng chính. Vì trong trường hợp sử dụng của chúng tôi, chúng tôi không có bất kỳ hướng dẫn nào được thực hiện sau thao tác chuyển đổi, luồng chính sẽ đợi cho đến khi luồng con kết thúc quá trình thực hiện

Tuy nhiên, chúng ta có thể chia hoạt động chuyên sâu của CPU (chuyển đổi JSON sang XML) thành nhiều phần và gán từng phần cho một luồng riêng biệt. Chúng ta có thể gán từng phần cho các luồng công nhân riêng biệt hoặc chúng ta có thể gán một phần cho luồng công nhân và phần còn lại chúng ta có thể để luồng chính xử lý. Dù bằng cách nào, chúng tôi sẽ có nhiều hơn một luồng hoạt động song song trên hoạt động. Hiện tại, giả sử chúng ta muốn giữ luồng chính miễn phí cho một số tác vụ khác và thực hiện theo cách tiếp cận thực thi trong hai luồng công nhân

Mặc dù chúng ta có thể đạt được trường hợp sử dụng trên bằng cách tạo một mảng các luồng công nhân, nhưng sẽ tốt hơn nếu sử dụng thư viện tổng hợp luồng công nhân sẽ đơn giản hóa và trừu tượng hóa việc quản lý các luồng công nhân cho chúng ta

Tình huống 3 - Thực thi song song với hai luồng công nhân

Ở đây, chúng tôi phân tích cú pháp và chuyển đổi JSON thành hai phần. Một nửa nội dung được chuyển đổi (50 tệp JSON), chúng tôi sẽ gán cho một luồng công nhân và nửa nội dung còn lại, chúng tôi sẽ gán cho một luồng công nhân khác. Để quản lý worker thread, chúng ta sẽ sử dụng thư viện tổng hợp có tên là piscina

⏰ Thời gian thực hiện trung bình. 687 mili giây

Sử dụng hai luồng công nhân, chúng ta có thể thấy thời gian thực hiện giảm đáng kể so với các kịch bản trước đó. Có nhiều hơn một luồng xử lý song song các phần của hoạt động chuyên sâu của CPU làm tăng đáng kể hiệu suất chương trình của chúng tôi

Tiếp theo, chúng ta hãy thử chia nhỏ thao tác trên hơn nữa để chúng ta có thể sử dụng nhiều luồng hơn và xem tác động đến hiệu suất

Dưới đây, bạn có thể tìm thấy thời gian thực hiện mà tôi đã ghi lại với số lượng luồng công nhân khác nhau bằng thư viện piscina

Không. của Worker Threads 2345678 Thời gian thực hiện (tính bằng mili giây)687577476502527558609

Chủ đề Nodejs

Từ dữ liệu trên, chúng ta có thể thấy rằng thời gian thực hiện tiếp tục giảm cho đến khi có 4 luồng công nhân và sau đó, nó bắt đầu tăng dần. Nhiều luồng hơn cũng có nghĩa là nhiều thời gian hơn để tạo luồng, giao tiếp giữa các luồng và chuyển ngữ cảnh

ghi chú cuối cùng

Việc sử dụng các luồng công nhân để xử lý song song các hoạt động chuyên sâu của CPU sẽ mang lại những cải tiến hiệu suất đáng kể. Tuy nhiên, điều này không có nghĩa là nhiều luồng hơn tương ứng trực tiếp với hiệu suất tốt hơn

Chúng ta cũng có thể sử dụng ArrayBuffer và SharedArrayBuffer để thực hiện truyền hoặc chia sẻ bộ nhớ giữa các luồng để thực thi hiệu quả hơn

Xem xét tất cả những điều trên, chúng ta cần quyết định số luồng tối ưu nhất để mang lại hiệu suất tốt nhất cho trường hợp sử dụng

Chủ đề trong Nodejs là gì?

Chủ đề. Các luồng giống như các quy trình. chúng có con trỏ lệnh riêng và có thể thực thi một tác vụ JavaScript tại một thời điểm . Không giống như các quy trình, các luồng không có bộ nhớ riêng. Thay vào đó, chúng nằm trong bộ nhớ của một tiến trình.

Bạn có thể tạo chủ đề trong Nodejs không?

Luồng công nhân được tạo bằng cách nhập mô-đun worker_threads của Node và gọi hàm tạo Worker() mới . Một quy trình mới sẽ được sinh ra để thực thi tệp JavaScript mà bạn chỉ định. Bạn có thể trao đổi tin nhắn với nhân viên để nhận thông báo khi có sự kiện xảy ra, dữ liệu đã sẵn sàng để xử lý hoặc xảy ra lỗi.

Làm thế nào worker thread hoạt động trong Nodejs?

Công việc của chuỗi worker là thực thi mã đã được chỉ định bởi chuỗi gốc hoặc chuỗi chính . Mỗi công nhân hoạt động độc lập. Mặt khác, một công nhân và cha mẹ của nó có thể giao tiếp qua kênh tin nhắn.

Nút js có nhóm luồng không?

Trong nút. js có hai loại chủ đề. một Vòng lặp sự kiện (còn gọi là vòng lặp chính, luồng chính, luồng sự kiện, v.v. ) và nhóm k Công nhân trong Nhóm công nhân (hay còn gọi là nhóm luồng) . Nếu một luồng mất nhiều thời gian để thực hiện gọi lại (Vòng lặp sự kiện) hoặc một tác vụ (Công nhân), chúng tôi gọi nó là "bị chặn".