I/O, Lưu trữ & Tài nguyên/Mini-challenge — đo ổ đĩa của chính bạn
8/26
Bài 8 / 26~18 phútLưu trữ & FilesystemMiễn phí lượt xem

Mini-challenge — đo ổ đĩa của chính bạn

Dùng dd, fio và drop_caches để tự đo tuần tự với ngẫu nhiên, bắt quả tang page cache nói dối, rồi đối chiếu số đo với thang độ trễ đã học ở cs-memory.

Cả module này lập luận về ổ đĩa bằng cơ chế: đầu đọc phải di chuyển, NAND phải xoá trước khi ghi, page cache đứng chắn ở giữa, fsync bắt bạn chờ. Bây giờ tới lượt bạn bắt máy tự khai — chạy bốn phép đo trên chính phần cứng của mình rồi giải thích những con số nhận được.

Bài này không có đáp án in sẵn để đối chiếu. Ổ của bạn khác ổ của tôi, và đó mới là điểm chính: thứ bạn phải rút ra không phải một con số, mà quan hệ giữa các con số và cơ chế nào tạo ra quan hệ đó.

🎯 Đề bài

Đo bốn thứ trên máy của bạn, ghi lại kết quả, rồi trả lời bốn câu hỏi ở cuối.

  1. Đọc tuần tự khối lớn — đọc một file cỡ 1 GB bằng khối 1 MB.
  2. Đọc ngẫu nhiên khối nhỏ — đọc rải rác trong file đó bằng khối 4 KB.
  3. Bắt quả tang page cache — đo cùng một phép đọc ba lần: lần đầu khi cache nguội, lần hai ngay sau đó, rồi lần ba sau khi xoá cache.
  4. Giá của độ bền — ghi một nghìn bản ghi nhỏ, một lần có gọi fsync sau mỗi bản ghi và một lần không.

Bốn câu hỏi phải trả lời được bằng số của chính bạn:

  • Tuần tự nhanh hơn ngẫu nhiên bao nhiêu lần? Con số đó nói gì về loại ổ bạn đang dùng?
  • Lần đọc thứ hai nhanh hơn lần đầu bao nhiêu lần? Dữ liệu lúc đó đang nằm ở đâu?
  • Sau khi xoá cache, số đo quay về gần lần đầu hay gần lần hai? Vì sao?
  • fsync sau mỗi bản ghi làm thông lượng đổi bao nhiêu? Vì sao chi phí đó không tỉ lệ với lượng dữ liệu?

🔍 Đầu vào — Xử lý — Đầu ra

Đầu vàoMột máy có ổ đĩa thật (không phải ổ mạng), ~2 GB trống, quyền sudo cho bước xoá cache
Xử lýBốn phép đo ở trên, mỗi phép chạy ít nhất hai lượt để loại nhiễu
Đầu raMột bảng bốn dòng ghi số đo của bạn, kèm bốn câu trả lời giải thích bằng cơ chế

📦 Bạn sẽ dùng lại những gì

  • HDD, SSD, NVMe — cơ chế vật lý quyết định con số bạn sắp thấy, và số hàng đợi quyết định phép đo song song có ý nghĩa hay không.
  • Tuần tự vs ngẫu nhiên — ba chỉ số IOPS, throughput, latency và quan hệ giữa chúng.
  • Page cache và buffered I/O — vì sao phép đo thứ ba mới là phép đo thành thật.
  • fsync và độ bền — vì sao độ bền tính tiền bằng độ trễ chứ không bằng băng thông.

▶️ Chuẩn bị

Đọc trước khi chạy

Bước xoá page cache cần quyền sudo và làm cả máy chậm đi trong chốc lát vì mọi thứ phải nạp lại từ đĩa. Đừng chạy bài này trên máy production. Trên máy ảo hoặc container, số đo có thể phản ánh tầng ảo hoá bên dưới chứ không phải ổ vật lý — vẫn học được, nhưng hãy biết mình đang đo cái gì.

Cách xoá page cache khác nhau theo hệ điều hành:

# Linux (ke ca WSL2): ghi 3 de xoa page cache + dentry + inode cache
sync && echo 3 | sudo tee /proc/sys/vm/drop_caches

# macOS: khong co drop_caches, dung lenh purge
sync && sudo purge

Công cụ: dd có sẵn mọi nơi và đủ cho phép đo tuần tự. fio mạnh hơn nhiều cho phép đo ngẫu nhiên — cài bằng apt install fio, dnf install fio hoặc brew install fio. Nếu không cài được fio thì phần ngẫu nhiên vẫn làm được bằng một script nhỏ đọc seek ngẫu nhiên, chỉ kém chính xác hơn.

Tạo file thử:

# Tao file 1 GB de doc. Dung /dev/urandom de tranh filesystem toi uu
# vung toan so 0 thanh sparse file - luc do ban do vao khong khi.
dd if=/dev/urandom of=testfile bs=1M count=1024 status=progress
sync

💡 Gợi ý

Đây là các câu hỏi định hướng, không phải lời giải. Trả lời được chúng thì bạn tự ra kết quả.

Về cách đo cho đúng. Mỗi phép đo nên chạy ít nhất hai lượt — lượt đầu thường bị nhiễu bởi việc nạp chương trình và cấp phát. Bạn cần quyết định: đo lượt nào, hay lấy trung bình? Và giữa hai phép đo khác nhau, trạng thái cache có được phép mang theo không?

Về việc chọn tham số. dd nhận bs (kích thước khối) và count (số khối). Tích của chúng là tổng dung lượng — muốn so tuần tự với ngẫu nhiên công bằng thì tổng dung lượng đọc nên giống nhau hay số thao tác nên giống nhau? Hai lựa chọn đó trả lời hai câu hỏi khác nhau; hãy chọn có ý thức.

Công thức để tự thay số:

so thao tac  = tong dung luong / kich thuoc khoi
throughput   = tong dung luong / thoi gian
IOPS         = so thao tac / thoi gian
do tre TB    = thoi gian / so thao tac

Về phép đo page cache. Sau khi đọc xong một file, nội dung nó nằm ở đâu? Lệnh free -h có cột nào thay đổi sau lần đọc đầu tiên không? Nếu bạn đọc lần hai mà không xoá cache, thứ bạn đang đo là tốc độ của thiết bị nào?

Về phép đo fsync. Ghi một nghìn bản ghi nhỏ tốn bao nhiêu byte tổng cộng? So con số đó với thời gian đo được: nếu chi phí đến từ băng thông thì thời gian phải tỉ lệ với số byte. Nó có tỉ lệ không? Nếu không, đại lượng nào mới là thứ nhân lên một nghìn lần?

Về fio. Hai tuỳ chọn đáng đọc kỹ trong tài liệu: --direct--iodepth. Cái thứ nhất quyết định phép đo có đi qua page cache hay không. Cái thứ hai quyết định bạn đang đo một hàng đợi nông hay sâu — mà theo bài 01, độ sâu hàng đợi lại chính là chỗ NVMe khác SATA.

✅ Lời giải

Dưới đây là cách chạy và cách đọc kết quả. Số cụ thể của bạn sẽ khác; cái cần khớp là quan hệ giữa các số.

Phép 1 — đọc tuần tự

sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
dd if=testfile of=/dev/null bs=1M status=progress

dd in ra thời gian và tốc độ ở dòng cuối. Đây là con số thân thiện nhất với ổ đĩa: khối lớn, địa chỉ liền mạch, read-ahead của kernel đoán trúng mọi lần.

Phép 2 — đọc ngẫu nhiên

sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
fio --name=random --filename=testfile --rw=randread \
    --bs=4k --size=256M --direct=1 --iodepth=1 --numjobs=1

--direct=1 bỏ qua page cache để đo thiết bị thật. --iodepth=1 giữ hàng đợi nông, tức là đo độ trễ một thao tác chứ không đo thông lượng tối đa.

Cách đọc: so IOPS của phép này với IOPS suy ra từ phép 1 (lấy throughput chia cho kích thước khối). Nếu chênh lệch nằm ở khoảng vài chục lần thì bạn gần như chắc chắn đang dùng ổ thể rắn. Nếu chênh vài trăm tới hàng nghìn lần, và độ trễ mỗi thao tác rơi vào thang mili-giây, thì đó là ổ quay — con số đó chính là tổng của seek cộng chờ quay mà bài 01 đã tính bằng số học.

Một điểm dễ bỏ sót: thử lại phép này với --iodepth=32. Trên SATA, IOPS sẽ tăng tới một trần rồi đứng; trên NVMe nó còn tăng tiếp khá xa. Đó là bảng hàng đợi ở bài 01 hiện ra thành số đo.

Phép 3 — bắt quả tang page cache

# Lan 1: cache nguoi
sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
time dd if=testfile of=/dev/null bs=1M count=512

# Lan 2: ngay sau do, KHONG xoa cache
time dd if=testfile of=/dev/null bs=1M count=512

# Lan 3: xoa cache roi do lai
sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
time dd if=testfile of=/dev/null bs=1M count=512

Cách đọc: lần hai sẽ nhanh hơn lần một rất nhiều, và lần ba quay về gần bằng lần một. Lý do là lần hai không hề chạm tới ổ đĩa — dữ liệu đã nằm trong page cache, nên thứ bạn đo là tốc độ RAM. Chạy free -h xen giữa các lần, bạn sẽ thấy cột buff/cache phình lên sau lần một rồi xẹp sau khi xoá.

Đây là kết luận đáng giá nhất của cả bài lab: mọi benchmark ổ đĩa không xoá cache đều đang đo RAM. Con số đẹp đến mức vô lý gần như luôn có nghĩa là bạn quên bước này, chứ không phải ổ của bạn thần kỳ.

Phép 4 — giá của độ bền

# Ghi 1000 ban ghi nho, KHONG fsync
fio --name=nosync --rw=write --bs=4k --size=4M \
    --fsync=0 --filename=w1

# Ghi 1000 ban ghi nho, fsync sau MOI ban ghi
fio --name=withsync --rw=write --bs=4k --size=4M \
    --fsync=1 --filename=w2

Cách đọc: tổng dữ liệu ghi là như nhau ở cả hai lượt — chỉ 4 MB. Nếu chi phí đến từ băng thông thì hai lượt phải mất thời gian xấp xỉ nhau. Thực tế lượt có fsync chậm hơn hẳn, thường là hàng chục lần trở lên.

Lý do: thứ bị nhân lên một nghìn lần không phải số byte mà là số lần chờ thiết bị xác nhận. Mỗi fsync là một vòng đi và về, và bạn trả nó một nghìn lần bất kể mỗi lần chỉ mang theo 4 KB. Đây chính là lý do database gom nhiều giao dịch rồi đồng bộ một lần thay vì đồng bộ sau mỗi thao tác.

Bảng tổng hợp

Điền số của bạn vào, rồi kiểm tra xem bốn dòng có kể một câu chuyện nhất quán không:

Phép đoKết quả của bạnCơ chế giải thích
Tuần tự 1 MBread-ahead trúng, không nhảy chỗ
Ngẫu nhiên 4 KBmỗi thao tác trả trọn chi phí định vị
Đọc lại khi cache nóngkhông chạm ổ, đang đo RAM
Ghi kèm fsynctrả tiền theo số lần chờ, không theo số byte

🎓 Mở rộng

  • Đo trên hai loại thiết bị. Nếu có cả SSD lẫn ổ ngoài USB hoặc thẻ nhớ, chạy lại phép 1 và 2 trên cả hai. Tỉ số tuần tự trên ngẫu nhiên sẽ rất khác nhau, và chính tỉ số đó là dấu vân tay của cơ chế bên dưới.
  • Đo fdatasync thay cho fsync. fio có tuỳ chọn --fdatasync=1. Chênh lệch giữa hai lượt cho bạn thấy giá của một lần cập nhật metadata — đúng thứ bài 05 lập luận.
  • Thử --iodepth tăng dần từ 1 lên 64 và vẽ IOPS theo độ sâu. Chỗ đường cong đi ngang chính là điểm bão hoà thật của thiết bị, và nó hữu ích hơn nhiều so với con số IOPS đơn lẻ trên tờ quảng cáo.
  • Dọn dẹp: nhớ xoá testfile, w1, w2 sau khi xong.

✨ Điều bạn vừa làm được

Bạn vừa biến bốn lập luận trừu tượng thành bốn con số trên phần cứng của chính mình. Quan trọng hơn, bạn có một quy trình đo trung thực: xoá cache trước khi đo thiết bị, tách độ trễ khỏi thông lượng, và biết đại lượng nào mới thật sự bị nhân lên khi hệ thống chậm.

Kỹ năng này dùng lại nguyên vẹn ở module 3, khi bạn phải phân xử một máy đang chậm là nghẽn CPU, RAM hay I/O — cũng bằng bằng chứng, không bằng phỏng đoán.

Bài tiếp theo: Tổng kết module — Lưu trữ & Filesystem

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

Bài tiếp theo

Tổng kết module — Lưu trữ & Filesystem