JavaScript vốn đã được thiết kế như một con thú đơn luồng. Tuy nhiên, trong địa hình hoang dã của điện toán, những kẻ săn mồi được gọi là 'bộ xử lý đa xử lý' và 'bộ xử lý đa lõi' đang chờ bị thuần hóa, sẵn sàng tăng khả năng thực thi mã của bạn lên tốc độ chưa từng có. 💪🚀
Tôi đã dám bước vào khu rừng này, đặt mã của mình vào bài kiểm tra sinh tồn cuối cùng và xuất hiện với kết quả đáng kinh ngạc. 🏆 Bây giờ, đến lượt bạn tham gia cùng tôi trong cuộc tìm kiếm đầy mê hoặc này. Chúng ta sẽ tìm hiểu sâu về bí ẩn của đa xử lý trong Node.js , được trang bị các ví dụ về mã hấp dẫn và thắp sáng ngọn đuốc 🔦 trên những thành quả ngoạn mục trong các thử nghiệm của tôi. 🍎🍏
Hãy sẵn sàng ra khơi trong cuộc phiêu lưu đầy kích thích này nhằm tăng cường hiệu suất JavaScript thông qua sự kỳ diệu của đa xử lý! Hãy thắt dây an toàn và chuẩn bị tinh thần khi chúng ta sắp bước vào lĩnh vực đầy mê hoặc của mã hóa có chỉ số octan cao.
Trước khi mạo hiểm quá sâu, hãy trang bị cho mình một số công cụ đáng tin cậy. Chúng ta sẽ tạo ra một số chức năng phụ trợ để mô phỏng công việc tính toán thường khó khăn. Hãy tạo một tạo phẩm mới, một tệp có tên utils.js
và ghi những câu thần chú cần thiết này vào đó.
// utils.js function generateRandomData(size) { const data = []; for (let i = 0; i < size; i++) { data.push(Math.random()); } return data; } function processData(data) { // performs some calculations on the array // to simulate high resource intensity let sum = 0; for (let num of data) { for (let j = 0; j < 1000000; j++) { sum += Math.sqrt(num); } } return sum; } module.exports = { generateRandomData, processData, };
Thực thi trong một luồng duy nhất thể hiện một cách tiếp cận chăm chỉ và đáng tin cậy để giải quyết vấn đề. Phiên bản đơn luồng của tập lệnh có thể được mô tả trực quan như vậy. Mã của phiên bản đơn luồng khá đơn giản. Chúng tôi tạo dữ liệu và gửi đi để xử lý.
// sync.js const { generateRandomData, processData } = require("./utils"); const data = generateRandomData(30000); console.time("single-thread. Time:"); processData(data); console.timeEnd("single-thread. Time:");
Chúng tôi khởi chạy tập lệnh bằng lệnh: node sync.js
Chúng tôi chờ đợi... và chờ đợi... và chờ đợi...
Và sau ngần ấy thời gian chờ đợi, chúng ta nhận được một thông báo cho biết thời gian thực thi của script.
single-thread. Time:: 25.888s
Cách tiếp cận này phù hợp với hóa đơn cho hầu hết các trường hợp. Nhưng có một trục trặc. Ai, trong tâm trí đúng đắn, yêu thích nghệ thuật chờ đợi? Để khắc phục sự chậm trễ đau đớn này, chúng ta phải khai thác toàn bộ hỏa lực của máy tính! Xét cho cùng, hầu hết các máy tính hiện đại đều được trang bị nhiều hơn một lõi CPU!
Vì vậy, tại sao chúng ta nên để các lõi bổ sung đó không hoạt động khi chúng có thể xử lý các con số và tăng tốc quá trình thực thi mã của chúng ta ? Đã đến lúc thắp sáng những gã khổng lồ đang say ngủ đó và mở khóa sức mạnh thô của đa xử lý! Hãy đi sâu vào!
Bằng cách áp dụng phương pháp đa xử lý, chúng tôi có thể tận dụng nhiều lõi của CPU, thúc đẩy hiệu suất tập lệnh của chúng tôi lên gấp nhiều lần. Quá trình hoạt động của mã đa xử lý của chúng tôi có thể được hình dung bằng sơ đồ này.
Về bản chất, chúng tôi chỉ đơn giản là phân vùng một tập dữ liệu khá lớn thành các phân đoạn và gán từng phân đoạn để xử lý cho một lõi CPU riêng biệt.
Tạo một tệp có tên multi-process.js
và điền nội dung sau vào tệp đó.
// multi-process.js const childProcess = require("child_process"); const utils = require("./utils"); const data = utils.generateRandomData(30000); const chunkSize = Math.ceil(data.length / 4); const chunks = []; for (let i = 0; i < 4; i++) { const start = i * chunkSize; const end = start + chunkSize; chunks.push(data.slice(start, end)); } console.time("multiProcessed"); const workers = []; let results = []; // result collection array for (let i = 0; i < chunks.length; i++) { const worker = childProcess.fork("./worker.js"); // pass its number and data to the workflow worker.send({ workerNumber: i, data: chunks[i] }); workers.push( new Promise((resolve, reject) => { worker.on("message", (result) => { results.push(result); // add the result to the result array resolve(); }); worker.on("error", reject); worker.on("exit", (code) => { if (code !== 0) { reject(new Error(`Worker stopped with exit code ${code}`)); } }); }) ); } Promise.all(workers) .then(() => { console.timeEnd("multiProcessed"); console.log("Processing results:", results); }) .catch((err) => console.error(err));
Mã này tiết lộ sự phối hợp của một quy trình worker đơn độc trong bản giao hưởng xử lý dữ liệu đa xử lý trong Node.js.
Tóm lại, đây là những gì đang xảy ra:
Công nhân nhận dữ liệu và số của nó từ quy trình chính thông qua process.on('message')
.
Hàm processData
thực hiện các tính toán trên phần dữ liệu được gán cho nhân viên này.
Kết quả được gửi trở lại quy trình chính thông qua ` process.send()``.
Công nhân kết thúc với mã 0 thông qua process.exit()
.
Kích hoạt tập lệnh bằng lệnh: node multi-process.js
Giữ chặt để tăng tốc...
Và chúng tôi nhận được kết luận rằng mã hoạt động trong 5 giây!
Worker 0 started Worker 1 started Worker 2 started Worker 3 started ==================== Worker 1 finished ==================== Worker 2 finished ==================== Worker 3 finished ==================== Worker 0 finished multiProcessed: 5.266s Processing results: [ 4971422688.053512, 4989646323.157899, 4999088030.661542, 5008034869.924775 ]
Kịch bản của chúng tôi đã hoạt động nhanh hơn gấp bốn lần! Không phải là tuyệt vời?
Với sự tò mò háo hức, tôi đã chạy cả hai tập lệnh trên máy tính được trang bị bộ xử lý 4 nhân, chờ đợi để chứng kiến điều kỳ diệu mở ra:
Nghệ sĩ solo, tập lệnh đơn luồng của chúng tôi, đã siêng năng xử lý dữ liệu trong 25,8 giây .
Nhóm đầy sức mạnh, tập lệnh đa luồng của chúng tôi, đã đánh bật nó ra khỏi công viên chỉ trong 5,2 giây !
Kìa sức mạnh của đa xử lý - hơn gấp bốn lần tốc độ tính toán!
Những sự tương phản rõ rệt này làm nổi bật cách đa xử lý có thể khuếch đại đáng kể khả năng tính toán của máy của bạn và giảm thời gian thực hiện.
Cuộc khám phá ly kỳ của chúng tôi vẽ nên một bức tranh sống động về cách đa xử lý có thể tăng tốc các tác vụ tính toán trong Node.js . Giải phóng mã của bạn trên mỗi lõi bộ xử lý sẽ mang lại một bước nhảy vọt rõ rệt về hiệu suất, giống như việc chuyển từ đi bộ sang dịch chuyển tức thời!
Chắc chắn là đáng để thêm mũi tên này vào hộp mã hóa của bạn và thử nghiệm phương pháp này trong các dự án của bạn. Và với sự ra đời của Worker Threads trong Node.js, việc triển khai đa xử lý đã trở nên dễ dàng.
Có một cơn sốt adrenaline đọc này? Vui lòng chia sẻ những cuộc phiêu lưu của riêng bạn với đa xử lý trong Node.js trong các nhận xét bên dưới! Hãy cùng nhau tiếp tục làm sáng tỏ những bí ẩn của mã hóa tốc độ cao.