CPU của bạn đang làm gì? os.cpus() và sức mạnh đa nhân Node.js
Nodejs

CPU của bạn đang làm gì? os.cpus() và sức mạnh đa nhân Node.js

Author

Admin System

@root

Ngày xuất bản

20 Mar, 2026

Lượt xem

2 Lượt

"os.cpus()"

Chào các chiến thần Gen Z! Hôm nay, anh Creyt sẽ cùng các em "mổ xẻ" một khái niệm nghe qua thì khô khan, nhưng lại cực kỳ quyền năng trong thế giới Node.js: os.cpus(). Hãy tưởng tượng thế này, máy tính của các em không chỉ là một cỗ máy đơn lẻ, mà nó giống như một nhà hàng lớn, và mỗi CPU core (lõi xử lý) chính là một "đầu bếp" chuyên nghiệp.

1. os.cpus() là gì và để làm gì? – "Đếm Đầu Bếp" và "Xem Thực Đơn"

Thằng os.cpus() này, nó nằm trong module os (operating system – hệ điều hành) của Node.js, đúng như tên gọi. Nhiệm vụ của nó "siêu đơn giản": nó sẽ trả về cho các em một array (mảng) các object (đối tượng), mà mỗi object đó đại diện cho một "đầu bếp" – tức là một CPU core – trong máy tính của các em. Không chỉ đếm số lượng, nó còn cho biết "lý lịch trích ngang" của từng đầu bếp nữa chứ!

Để làm gì ư? À, đây mới là phần hay nè. Khi các em muốn tối ưu hiệu năng của ứng dụng Node.js, đặc biệt là những ứng dụng phải xử lý nhiều tác vụ nặng (kiểu như tính toán phức tạp, xử lý ảnh/video, mã hóa/giải mã), thì việc biết được mình có bao nhiêu "đầu bếp" là cực kỳ quan trọng. Node.js vốn dĩ là single-threaded (đơn luồng) cho JavaScript runtime, nhưng với os.cpus(), các em có thể "đánh lừa" nó, biến nó thành một "nhà hàng đa đầu bếp" bằng cách tận dụng module cluster để phân chia công việc.

Nói cách khác, nó giúp các em:

  • Hiểu sức mạnh thật sự của server: "À, server mình có 8 core, vậy là có 8 đầu bếp khỏe mạnh, mình có thể giao nhiều việc hơn."
  • Tối ưu hiệu năng: Phân chia công việc cho các "đầu bếp" khác nhau để xử lý song song, tránh tình trạng một "đầu bếp" làm việc quá tải còn những người khác ngồi chơi xơi nước.
  • Scale ứng dụng: Chuẩn bị cho việc ứng dụng của các em "lên đời" và cần xử lý lượng request khổng lồ.

2. Code Ví Dụ Minh Hoạ – "Nhờ Thằng Quản Lý Báo Cáo Số Lượng Đầu Bếp"

Giờ thì chúng ta "xắn tay áo" vào code thôi. Anh Creyt đảm bảo code này dễ hiểu hơn cả việc order trà sữa nữa.

const os = require('os');

// Lấy thông tin tất cả các CPU core
const cpus = os.cpus();

console.log(`
--- Thông tin CPU của bạn ---
`);
console.log(`Bạn có tổng cộng ${cpus.length} "đầu bếp" (CPU cores) đang hoạt động.`);

// In ra thông tin chi tiết của từng "đầu bếp"
cpus.forEach((cpu, index) => {
  console.log(`
Đầu bếp số ${index + 1}:`);
  console.log(`  - Tên hiệu: ${cpu.model}`);
  console.log(`  - Tốc độ: ${cpu.speed / 1000} GHz`); // Tốc độ tính bằng MHz, chia 1000 để ra GHz
  console.log(`  - Thời gian hoạt động (ms):`);
  console.log(`    - User (làm việc): ${cpu.times.user}`);
  console.log(`    - Nice (ưu tiên thấp): ${cpu.times.nice}`);
  console.log(`    - Sys (hệ thống): ${cpu.times.sys}`);
  console.log(`    - Idle (nghỉ ngơi): ${cpu.times.idle}`);
  console.log(`    - Irq (ngắt): ${cpu.times.irq}`);
});

// Một ví dụ tính toán đơn giản về tổng thời gian CPU đã làm việc và nghỉ ngơi
const totalIdleTime = cpus.reduce((acc, cpu) => acc + cpu.times.idle, 0);
const totalBusyTime = cpus.reduce((acc, cpu) => acc + cpu.times.user + cpu.times.nice + cpu.times.sys + cpu.times.irq, 0);
const totalCPUTime = totalIdleTime + totalBusyTime;

console.log(`
--- Tình hình làm việc chung của các "đầu bếp" ---
`);
console.log(`Tổng thời gian nghỉ ngơi: ${totalIdleTime} ms`);
console.log(`Tổng thời gian bận rộn: ${totalBusyTime} ms`);
console.log(`Tỷ lệ bận rộn (ước tính): ${((totalBusyTime / totalCPUTime) * 100).toFixed(2)}%`);

Khi chạy đoạn code này, các em sẽ thấy một "báo cáo" chi tiết về tất cả các CPU core trên máy của mình, từ tên model, tốc độ, cho đến thời gian mà nó dành cho các tác vụ khác nhau (user, system, idle...). Cái times object này cực kỳ hay ho, nó cho các em biết "đầu bếp" nào đang "rảnh rỗi" hay "bận rộn" đến mức nào.

Illustration

3. Mẹo Vặt & Best Practices – "Bí Kíp Của Thằng Chủ Nhà Hàng Khôn Ngoan"

  • Đừng chỉ đếm, hãy hiểu: Số lượng core quan trọng, nhưng thông tin modelspeed cũng không kém. Một con CPU đời mới 4 core có thể mạnh hơn con CPU đời tống 8 core đấy. Luôn nhìn vào bức tranh tổng thể.
  • Kết hợp với cluster module: Đây là "cặp bài trùng" huyền thoại. os.cpus().length thường được dùng để xác định số lượng worker processes (tiến trình con) mà module cluster nên tạo ra. Ví dụ, nếu có 8 core, các em có thể tạo 8 worker process để mỗi "đầu bếp" đảm nhận một tiến trình, tối ưu hóa việc xử lý request.
    const cluster = require('cluster');
    const os = require('os');
    const numCPUs = os.cpus().length;
    
    if (cluster.isMaster) {
      console.log(`Master ${process.pid} is running. Spawning ${numCPUs} workers.`);
      for (let i = 0; i < numCPUs; i++) {
        cluster.fork(); // Tạo worker process cho mỗi CPU core
      }
      cluster.on('exit', (worker, code, signal) => {
        console.log(`Worker ${worker.process.pid} died. Forking a new one...`);
        cluster.fork(); // Tự động khởi tạo lại worker nếu có lỗi
      });
    } else {
      // Worker processes có thể chạy server HTTP hoặc các tác vụ nặng
      console.log(`Worker ${process.pid} started.`);
      // Ví dụ: app.listen(8000);
    }
    
  • Theo dõi "sức khỏe" CPU: Thông tin times là vàng đấy. Các em có thể dùng nó để xây dựng các công cụ giám sát, cảnh báo khi CPU quá tải. Một "đầu bếp" làm việc 100% thời gian không nghỉ là dấu hiệu của một server đang "nghẹt thở".
  • Tránh "lạm dụng": Không phải lúc nào cũng cần tạo ra số worker process bằng số lượng CPU core. Nếu ứng dụng của em chủ yếu là I/O-bound (chờ đợi dữ liệu từ database, network) chứ không phải CPU-bound, thì việc tạo quá nhiều worker đôi khi còn phản tác dụng do overhead quản lý tiến trình. Hãy test và điều chỉnh cho phù hợp.

4. Ứng Dụng Thực Tế – "Nhà Hàng Nào Đang Dùng Kỹ Thuật Này?"

Các em có thể đã và đang sử dụng những dịch vụ áp dụng nguyên lý này mà không hề hay biết:

  • Netflix, YouTube: Khi các em upload một video, quá trình mã hóa (encoding) video đó cần rất nhiều CPU. Các hệ thống này sẽ chia nhỏ video ra, và dùng nhiều "đầu bếp" (CPU cores/workers) để xử lý các phần khác nhau của video song song, giúp quá trình nhanh hơn gấp nhiều lần.
  • Các nền tảng thương mại điện tử lớn (Shopee, Lazada): Để xử lý hàng triệu request mỗi giây, các hệ thống backend của họ phải được tối ưu hóa để tận dụng tối đa tài nguyên server, trong đó có việc phân phối tải lên các CPU core khác nhau.
  • CI/CD Pipelines (ví dụ: Jenkins, GitLab CI): Khi chạy các bài test hoặc build dự án, các hệ thống này thường phân phối các job nhỏ hơn tới các agent (máy tính) khác nhau, và trên mỗi agent đó, họ lại tận dụng đa luồng/đa tiến trình để chạy test song song, giảm thời gian chờ đợi.

5. Thử Nghiệm & Hướng Dẫn Sử Dụng – "Trải Nghiệm Đau Thương Của Anh Creyt"

Anh Creyt nhớ hồi mới "vào nghề", cũng "ngây thơ" lắm. Cứ nghĩ Node.js là single-threaded thì cả thế giới chỉ chạy được một luồng. Thế là viết một cái API tính toán chuỗi Fibonacci cực dài, chạy trên một con server 4 core. Kết quả là gì? Một core làm việc "bạc mặt" 100%, 3 core còn lại "ngồi chơi xơi nước", và request thì xếp hàng dài cổ chờ xử lý. Cái API chậm như rùa bò!

Sau này, anh mới "ngộ" ra chân lý os.cpus()cluster. Anh đã thử nghiệm bằng cách sử dụng os.cpus().length để tạo ra số lượng worker processes bằng số core CPU. Kết quả là "một trời một vực"! Thời gian xử lý request giảm đi đáng kể, server cũng "thở phào nhẹ nhõm" hơn vì công việc được chia đều cho các "đầu bếp".

Vậy nên dùng os.cpus() trong những trường hợp nào?

  • Khi ứng dụng của em là CPU-bound: Tức là ứng dụng của em thực hiện nhiều phép tính toán phức tạp, xử lý dữ liệu nặng, mã hóa/giải mã, nén/giải nén...
  • Xây dựng các microservices hoặc API gateway: Để đảm bảo khả năng chịu tải và mở rộng khi có nhiều yêu cầu đồng thời.
  • Phát triển các công cụ giám sát hiệu năng: Để thu thập thông tin về CPU usage và đưa ra cảnh báo.
  • Khi muốn tối ưu hóa việc sử dụng tài nguyên trên một server vật lý: Thay vì chỉ chạy một tiến trình Node.js duy nhất, hãy tận dụng toàn bộ số core mà server có.
  • Dùng kèm với worker_threads (từ Node.js 10.5.0): Nếu các em muốn thực hiện các tác vụ CPU-bound trong cùng một tiến trình nhưng trên các luồng riêng biệt, worker_threads là một lựa chọn khác, và os.cpus().length vẫn có thể giúp các em quyết định số lượng worker threads nên tạo ra.

Nhớ nhé, các em Gen Z! Trong lập trình, hiểu rõ tài nguyên mình đang có trong tay là chìa khóa để xây dựng những ứng dụng "bất khả chiến bại". os.cpus() chính là "bản đồ kho báu" giúp các em khám phá sức mạnh tiềm ẩn của cỗ máy của mình. Cứ thực hành đi, rồi các em sẽ thấy nó "ngon" như thế nào!

Thuộc Series: Nodejs

Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

#tech #cyberpunk #laravel
Chỉnh sửa bài viết

Bình luận (0)

Vui lòng Đăng Nhập để Bình luận

Hỗ trợ Markdown cơ bản
Nguyễn Văn A
1 ngày trước

Tính năng này đỉnh quá ad ơi, chờ mãi mới thấy một blog Tiếng Việt có UI/UX xịn như vầy!