I/O, Lưu trữ & Tài nguyên/Tổng kết course & track — Máy tính cho Lập trình viên
26/26
Bài 26 / 26~8 phútTài nguyên & Đo lườngMiễn phí lượt xem

Tổng kết course & track — Máy tính cho Lập trình viên

Cheat sheet tài nguyên và đo lường, glossary, pitfall tổng hợp, self-assessment — và bản đồ khép lại cả bốn course của track computer-systems.

TL;DR: Module này đổi câu hỏi từ máy hoạt động thế nào sang làm sao biết máy đang tắc ở đâu. Cả năm bài quy về đúng một kỷ luật: trước khi hành động theo một chỉ số, hỏi xem nó đang đo cái gì và nó có còn đo đúng thứ đó trên phần cứng hôm nay không. Load average trộn CPU với I/O; RSS đếm trùng phần chia sẻ; %util sinh ra cho thiết bị một-việc-một-lúc. Đây là một trang để đánh dấu, và cũng là chỗ khép lại cả bốn course của track.

Đã đi qua những gì

Bạn bắt đầu bằng con số quen thuộc nhất và cũng bị hiểu sai nhiều nhất: load average. Hoá ra nó đếm cả những tiến trình đang nằm chờ đĩa, nên câu "load cao thì thêm CPU" sai ngay từ tiền đề. Từ đó, mỗi bài đều lặp lại cùng một mô típ — một chỉ số ai cũng dùng, một định nghĩa ít ai đọc, và khoảng cách giữa hai thứ đó chính là chỗ các quyết định sai được sinh ra.

Bài 02 mổ chuyện cộng RSS. Bài 03 mổ chuyện %util mất nghĩa trên NVMe. Bài 04 và 05 chuyển sang tầng ràng buộc mà container dựng lên: hạn ngạch theo chu kỳ, hai mức trần bộ nhớ, và khối log OOM là bằng chứng duy nhất còn lại sau một cú SIGKILL. Bài mini-challenge ghép tất cả thành một quy trình chạy được trong một phút.

Nam chi so cua module, moi cai kem cau hoi no that su tra loi

🗺️ Cheat sheet

Chỉ sốĐo cái gìPitfall hay gặp
Load averageSố tiến trình trạng thái R cộng D, trung bình 1/5/15 phútĐọc như phần trăm CPU; quên chia cho số lõi
Cột rb của vmstatTách nhu cầu CPU khỏi chờ I/OBỏ qua, rồi đoán mò từ load average
wa (iowait)Lõi rảnh trong khi có I/O treoCoi là bằng chứng; nó nhiễu nặng trên máy nhiều lõi
st (steal)Thời gian bị hypervisor lấy cho máy ảo khácBỏ qua rồi đi tối ưu code
VSZKhông gian địa chỉ đã đăng kýDùng để đặt hạn mức bộ nhớ
RSSTrang đang nằm trong RAMCộng RSS toàn máy rồi hoảng
PSSTrang chia sẻ chia theo số bên dùngQuên mất là có chỉ số này
awaitThời gian trọn vẹn một yêu cầu I/O, gồm cả chờĐổ ngay cho phần cứng khi nó cao
aqu-szSố yêu cầu trung bình đang trong hệ thốngCoi hàng đợi dài luôn là xấu
%utilTỉ lệ thời gian thiết bị có việcĐọc như phần trăm công suất trên NVMe
cpu.maxHạn ngạch CPU mỗi chu kỳ 100 msNhầm với nice; theo dõi mỗi mức trung bình
cpu.statnr_periods, nr_throttled, throttled_usecKhông có trên dashboard, nên không ai nhìn
memory.highBóp lại và ép thu hồi trangNhầm là một cách viết khác của memory.max
memory.maxTrần cứng, vượt là OOM trong cgroupĐặt -Xmx đúng bằng nó
constraint trong log OOMPhân biệt OOM toàn máy với OOM cấp cgroupThấy máy còn RAM rồi loại giả thuyết OOM
oom_score_adjDải -1000…1000, chỉnh khả năng bị chọnMiễn nhiễm cho một tiến trình mà quên sshd
RLIMIT_NOFILESố fd mở cùng lúc, mềm mặc định 1024Nâng bằng ulimit trong shell rồi tưởng đã xong

📖 Glossary module

Thuật ngữĐịnh nghĩa một câu
Load averageTrung bình có trọng số của số tiến trình đang chạy được hoặc đang kẹt chờ I/O, theo ba khung 1/5/15 phút.
Trạng thái DNgủ không ngắt được: tiến trình đang chờ một thao tác kernel không thể huỷ giữa chừng, điển hình là block I/O.
iowaitPhần thời gian lõi rảnh trong khi vẫn có yêu cầu I/O đang treo.
Steal timeThời gian CPU ảo bị hypervisor cấp cho máy ảo khác trên cùng phần cứng.
PSIChỉ số kernel đo tỉ lệ công việc bị đình trệ vì CPU, bộ nhớ hoặc I/O, tách hai mức somefull.
VSZTổng kích thước mọi vùng đã ánh xạ vào không gian địa chỉ ảo của tiến trình.
RSSSố trang của tiến trình đang thật sự cư trú trong RAM.
PSSCách đếm chia mỗi trang chia sẻ cho số tiến trình đang dùng, nên tổng toàn máy có nghĩa.
Trang ẩn danhTrang không có file nền (heap, ngăn xếp), chỉ thu hồi được bằng swap.
awaitThời gian trung bình của một yêu cầu I/O, tính cả quãng nằm trong hàng đợi.
aqu-szĐộ sâu hàng đợi trung bình, xấp xỉ bằng thông lượng nhân với await.
cgroupCơ chế kernel gom một nhóm tiến trình rồi đo đếm và áp trần tài nguyên lên cả nhóm.
ThrottlingViệc kernel treo cả cgroup tới đầu chu kỳ sau khi nhóm đã xài hết hạn ngạch CPU.
memory.highTrần mềm: vượt thì nhóm bị bóp lại và ép thu hồi trang, không bị giết.
memory.maxTrần cứng: thu hồi không đủ thì OOM killer ra tay trong phạm vi cgroup.
OOM killerCơ chế kernel chọn và hạ một tiến trình bằng SIGKILL khi không còn cách cấp thêm bộ nhớ.
oom_scoreĐiểm số quyết định khả năng bị chọn, tính xấp xỉ theo bộ nhớ đang giữ cộng phần điều chỉnh.
EMFILELỗi trả về khi tiến trình chạm trần số file descriptor được mở cùng lúc.
USE methodQuy trình hỏi Utilization, Saturation, Errors cho từng tài nguyên trước khi kết luận.

⚠️ Pitfall tổng hợp

Đọc load average như phần trăm CPU → ✅ Nó đếm cả tiến trình D; chia cho nproc, rồi tách bằng cột rb của vmstat.

Kết luận từ wa cao → ✅ Chỉ dấu, không phải bằng chứng; bằng chứng nằm ở await cùng số tiến trình D.

Bỏ qua st trên máy ảo cloud → ✅ Một phần tư thời gian CPU bị lấy mất thì không profiler nào tìm ra được, vì lỗi không nằm trong code.

Cộng RSS toàn máy → ✅ Phép cộng đếm trùng mọi trang chia sẻ; cảnh báo nên đặt trên dung lượng khả dụng và mức swap.

Dùng VSZ để đặt trần bộ nhớ → ✅ VSZ phồng vì vùng đăng ký trước và file ánh xạ; RSS hoặc memory.current mới là con số thật.

Báo động vì %util chạm 100% trên NVMe → ✅ Chỉ số đó bão hoà rất sớm với thiết bị phục vụ song song; đọc await cùng aqu-sz.

Đọc dòng đầu của iostat → ✅ Đó là trung bình từ lúc khởi động; luôn chạy dạng lặp và bỏ dòng đầu.

Dùng nice để giới hạn CPU → ✅ nice chỉ đổi tỉ lệ chia khi tranh chấp; trần cứng nằm ở cpu.max của cgroup.

Tin /proc/cpuinfo trong container → ✅ Tiến trình bị giới hạn 2 lõi vẫn thấy đủ 64 lõi của máy chủ, rồi dựng thread pool theo con số sai.

Theo dõi mức dùng CPU trung bình của pod → ✅ Trung bình che mất các đợt treo; nr_throttled chia nr_periods mới lộ ra đuôi trễ.

Đặt -Xmx đúng bằng memory.max → ✅ Ngoài heap còn metaspace, ngăn xếp mỗi thread và bộ đệm ngoài heap; chừa khoảng 25%.

Tìm nguyên nhân OOM trong log ứng dụng → ✅ SIGKILL không cho ghi thêm dòng nào; bằng chứng nằm ở dmesg trên máy chủ.

Nâng ulimit -n trong shell rồi tưởng service đã được nâng → ✅ Giới hạn đi theo tiến trình từ lúc khởi động; đặt ở unit file hoặc cấu hình container.

✅ Self-assessment

Bạn đã đạt module này nếu trả lời được:

  • Đo được tải hệ thống bằng tophtop, và đọc đúng nghĩa load average kể cả khi có tiến trình Dnếu chưa: bài 01 mục 2 và 4.
  • Phân biệt được RSS, VSZ và PSS để trả lời một tiến trình thật sự chiếm bao nhiêu RAM — nếu chưa: bài 02 mục 3 và 4.
  • Chẩn đoán được thiết bị lưu trữ có thật sự bão hoà không, dựa trên await và độ sâu hàng đợi — nếu chưa: bài 03 mục 3 và 4.
  • Giải thích được cgroups v2 áp trần CPU, RAM và I/O lên một nhóm tiến trình thế nào — nếu chưa: bài 04 mục 3.
  • Chẩn đoán được một lần OOM kill từ dmesg và phân biệt OOM cấp cgroup với OOM toàn máy — nếu chưa: bài 05 mục 2 và 4.
  • Giải thích được trần RLIMIT_NOFILE làm một service ngừng nhận kết nối mà vẫn sống thế nào — nếu chưa: bài 05 mục 5.

Chưa chắc mục nào thì cách kiểm tra thật nhất là mở một máy đang chạy thật, chạy năm lệnh của mini-challenge, và tự giải thích từng con số bạn nhìn thấy.

🧭 Khép lại khoá học

Ba module của khoá này trả lời ba câu hỏi nối tiếp nhau. Module 01 hỏi dữ liệu nằm ở đâu khi tắt điện: cơ chế vật lý của thiết bị, filesystem, page cache, và cái giá của fsync. Module 02 hỏi nó đi đường nào để tới được biến trong chương trình: thanh ghi thiết bị, DMA, tuyến đường của một lệnh read(), cách chờ, số bản sao, rồi GPU như ví dụ cực đoan nhất. Module 03 hỏi làm sao biết nó đang tắc ở đâu.

Ba câu hỏi ấy cũng là ba giai đoạn của mọi lần chẩn đoán thật: bạn cần bản đồ trước, rồi mới cần thước đo — và một người có thước mà không có bản đồ thì đọc số ra chữ, chứ không ra nguyên nhân.

🎓 Khép lại track — Máy tính cho Lập trình viên

Khoá này là tier 4, tức khoá cuối của track. Nhìn lại cả bốn:

CourseCâu hỏi nó đóng lại
Dữ liệu & CPUMáy biểu diễn dữ liệu bằng gì và chạy một lệnh ra sao
Bộ nhớChương trình bố trí bộ nhớ thế nào, và vì sao cache đổi được tốc độ
Hệ điều hành & Tiến trìnhAi thật sự chạy code của bạn, và nó xin phần cứng bằng cách nào
I/O, Lưu trữ & Tài nguyênDữ liệu ra vào máy thế nào, và làm sao biết máy đang tắc ở đâu

Điểm chung của cả bốn: chúng không dạy một công nghệ nào cụ thể. Framework sẽ đổi, ngôn ngữ sẽ đổi, nhưng chuyện một trang bộ nhớ phải được nạp trước khi đọc, một thao tác ngẫu nhiên đắt hơn một thao tác tuần tự, hay một chỉ số chỉ đúng trong bối cảnh nó ra đời — những thứ đó thì không.

🚀 Tiếp theo

Có ba hướng đi tự nhiên từ đây, tuỳ thứ bạn đang cần:

  • Hệ thống Dữ liệu Phân tán — mọi giới hạn bạn vừa học ở một máy trở thành ràng buộc thiết kế khi lên nhiều máy: nhân bản, phân mảnh, đồng thuận.
  • Mạng máy tính — nửa còn lại của bức tranh I/O, lần theo một request từ URL tới response.
  • JVM internals — nếu bạn viết Java, bài về bộ nhớ ngoài heap là chỗ nối thẳng với memory.max và OOM cấp cgroup của module này.

📚 Tài liệu mở rộng

Quay lại: Danh mục khoá học

Bài này đáng gửi cho bạn học cùng?

Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.

Bài này có giúp bạn hiểu bản chất không?

Hỏi đáp về bài này

Chưa có câu hỏi

Đặt câu hỏi

Có gì chưa rõ trong bài? Đặt câu hỏi đầu tiên — câu trả lời từ cộng đồng giúp bạn (và người sau).

Đặt câu hỏi đầu tiên