🖥️ OS✍️ Khoa📅 19/04/2026☕ 5 phút đọc

OS & Concurrency: Monitoring, So sánh và Cloud

8. System Monitor Chart — Đọc hiểu

CPU Usage % thực sự nghĩa là gì?

CPU Usage % = (thời gian RUNNING) / (tổng thời gian) × 100

Ví dụ Core 0 trong 1 giây:
  RUNNING : 700ms → CPU Usage = 70%
  IDLE    : 300ms

⚠️ "CPU 100%" không có nghĩa là đang tính toán hữu ích 100%. CPU có thể 100% nhưng phần lớn thời gian là context switching overhead — hệ thống bận nhưng không làm việc thật.

Phân loại CPU time

██████████ User   (xanh lá)  — code ứng dụng đang chạy
████       System (đỏ)       — kernel đang chạy (syscalls, interrupts)
░░░░░░     Idle   (trống)    — không có gì chạy

System time cao bất thường thường chỉ điểm ứng dụng đang gọi quá nhiều syscalls (ví dụ: tạo quá nhiều connections, đọc file nhiều small chunks).

Đọc chart đa core

Core 0  [████████░░] 80%
Core 1  [████░░░░░░] 40%
Core 2  [██████████] 100%  ← bottleneck! (single-threaded?)
Core 3  [░░░░░░░░░░] 0%   ← hoàn toàn nhàn

Average hiển thị: (80+40+100+0)/4 = 55%

Average 55% nghe có vẻ bình thường, nhưng thực ra Core 2 đang bị nghẽn trong khi Core 3 hoàn toàn nhàn. Đây là dấu hiệu của code chưa được parallel hóa tốt.

Load Average (Linux)

$ uptime
2.5  1.8  1.2
1min  5min  15min

Load = số threads đang RUNNING + WAITING FOR CPU (không phải BLOCKED)

Rule of thumb:

Load = 1.0 trên 1 core  → vừa đủ tải
Load = 4.0 trên 4 cores → vừa đủ (100% utilized)
Load = 8.0 trên 4 cores → QUÁ TẢI — threads đang xếp hàng chờ core

Load average tăng dần (1min > 5min > 15min) → vấn đề đang leo thang. Load average giảm dần → đang phục hồi.

Context Switches/sec

< 10,000/s   → bình thường, ít threads tranh CPU
> 100,000/s  → nhiều threads đang tranh nhau → dấu hiệu nên
               dùng goroutine/async thay vì OS thread

9. So sánh tổng quan

                Physical    OS Thread    Goroutine
                Thread
─────────────────────────────────────────────────────
Lớp             Hardware    Kernel       Go Runtime
Quản lý bởi     CPU         Kernel       Go runtime
RAM             N/A         1-8 MB       2 KB (ban đầu, dynamic)
Stack           N/A         Cố định      Tự động grow
Tạo mới         N/A         ~1 ms        ~300 ns
Context switch  N/A         ~1-10 µs     ~100 ns
Giới hạn        = CPU cores ~10,000      ~1,000,000+
Giao tiếp       N/A         Mutex/Lock   Channel (an toàn hơn)
Kernel biết?    Có          Có           Không

Ví dụ thực tế: Web server xử lý 10,000 requests

Java (OS Threads truyền thống):
  10,000 requests → 10,000 OS threads
  10,000 × 1MB = ~10 GB RAM chỉ cho threads
  Context switching liên tục → CPU gần như chỉ switch
  → 💥 Server chết

Go (Goroutines):
  10,000 requests → 10,000 goroutines
  10,000 × 2KB = ~20 MB RAM
  8 OS threads xoay vòng phục vụ tất cả
  → ✅ Mượt mà, hiệu quả

10. Tại sao Go mạnh trong Cloud

Goroutines xử lý concurrency ở quy mô lớn

// Tạo 1 triệu goroutine — bình thường với Go
for i := 0; i < 1_000_000; i++ {
    go handleRequest(i)
}
// RAM dùng: ~2 GB (so với ~1 TB nếu dùng OS threads)

Đây là lý do Go servers có thể handle hàng trăm nghìn concurrent connections trên một máy bình thường.

Static Binary: deploy cực nhanh

app.go  →  ./app  (1 file, không cần JVM, không cần interpreter)

→ Docker image: vài MB (thay vì hàng trăm MB)
→ Khởi động: milliseconds
→ Lý tưởng cho serverless và container

Low-latency Garbage Collector

Java GC có thể gây "stop-the-world" pause đột ngột — latency spike khi GC chạy. Go GC concurrent với latency thường dưới 1ms. Quan trọng với SLA yêu cầu p99 latency thấp.

Standard Library mạnh

net/http        — HTTP server/client built-in
encoding/json   — JSON nhanh built-in
context         — timeout, cancellation cho distributed systems
crypto/tls      — TLS/HTTPS built-in

Không cần framework nặng để dựng API server hiệu năng cao. Một production HTTP server có thể dùng hoàn toàn standard library.

Hệ sinh thái Cloud "sinh ra từ Go"

Công cụ Vai trò
Docker Container runtime
Kubernetes Container orchestration
Terraform Infrastructure as Code
Prometheus Monitoring
etcd Distributed key-value store
Consul Service discovery

Phần lớn infrastructure tooling hiện đại được viết bằng Go — có lý do cho điều đó.

Ngôn ngữ đơn giản, dễ maintain ở scale lớn

Go chỉ có ~25 keywords. Không có class inheritance phức tạp, không có magic ẩn. Hàng trăm engineers có thể maintain cùng codebase mà không có quá nhiều "what does this do?" moments.


🗺️ Bức tranh tổng thể

Bạn viết code Go
    │
    ▼
Goroutine (2KB, hàng triệu cái)
    │  Go runtime M:N scheduler
    ▼
OS Thread (~8 cái, bằng số cores)
    │  Kernel CFS scheduler (vruntime, red-black tree)
    ▼
Physical Core (thực thi thật: fetch → decode → execute)
    │
    ▼
Kết quả (register → L1/L2/L3 cache → RAM)
    │
    ▼
System Monitor: đo % thời gian core đang RUNNING → hiển thị chart