Phần trước đo nice và tìm ra nó chỉ có tác dụng khi hai tiến trình cùng một nhân. Bài này đo bốn cách đổi ưu tiên trong đúng điều kiện đó.

Bốn cách đổi ưu tiên với kết quả đo, và giới hạn 95% của thời gian thực

Bốn cách, một phép thử

Hai tiến trình tính toán ghim vào cùng một nhân, chỉ khác ưu tiên của cái thứ hai.

Cách đổi ưu tiên Tiến trình thường Tiến trình được đổi
nice 19 98,7% 1,3%
chrt -i (SCHED_IDLE) 99,7% 0,3%
chrt -b (SCHED_BATCH) 50,0% 50,0%
chrt -r 10 (thời gian thực) 5,0% 95,0%

Ba kết quả đáng nói.

SCHED_BATCH không hạ ưu tiên chút nào

50/50 — y hệt như không làm gì.

Đây là hiểu nhầm phổ biến: tên gọi "batch" nghe như "chạy khi rảnh". Thực ra nó không đụng vào trọng số; trọng số vẫn 1024 như tiến trình thường.

SCHED_BATCH chỉ nói với nhân: tiến trình này không cần phản hồi nhanh, đừng đánh thức nó sớm khi nó trở nên sẵn sàng. Kết quả là ít lần chuyển ngữ cảnh hơn và bộ nhớ đệm CPU ấm hơn — có lợi cho thông lượng của chính nó, không có lợi cho các tiến trình khác.

Dùng nó cho công việc tính toán dài không tương tác. Đừng dùng nó để nhường CPU.

SCHED_IDLE mạnh hơn nice 19 bốn lần

nice 19       1,3%
SCHED_IDLE    0,3%

nice 19 có trọng số 15 — nhỏ, nhưng vẫn là một phần của cùng công thức. SCHED_IDLE nằm ở lớp riêng, dưới toàn bộ SCHED_OTHER, và chỉ chạy khi không còn gì khác.

Với công việc nền thật sự — nén nhật ký, dọn dẹp, sao lưu — SCHED_IDLE là lựa chọn đúng:

chrt -i 0 ./cong-viec-nen

Nó không bao giờ làm chậm công việc chính, và nó vẫn chạy hết trong những khoảng máy rảnh.

Thời gian thực dừng đúng ở 95%

Trong 6 giây trên cùng một nhân:

tiến trình TS (thường)    30 jiffies
tiến trình RR (RT)       571 jiffies

Tỉ lệ 5% / 95%, và con số đó không ngẫu nhiên:

sched_rt_runtime_us = 950000
sched_rt_period_us  = 1000000

Nhân cố ý giữ lại 5% mỗi giây cho tiến trình thường. Đây là cơ chế chống treo máy: không có nó, một vòng lặp bận ở SCHED_FIFO sẽ chiếm 100% và bạn không còn cách nào đăng nhập để giết nó.

Nếu bạn từng đọc lời khuyên "đừng dùng SCHED_FIFO trừ khi biết rõ đang làm gì", đây chính là lý do — và 5% kia là tấm lưới duy nhất.

Có thể tắt lưới đó bằng sched_rt_runtime_us = -1. Đừng, trừ khi bạn đang xây hệ thống thời gian thực thật và có cách khác để phục hồi.

SCHED_FIFO so với SCHED_RR

Cả hai đều là thời gian thực và đều đứng trên CFS. Khác nhau một điểm:

  • SCHED_FIFO chạy tới khi tự nhường hoặc bị tiến trình RT ưu tiên cao hơn cắt ngang. Không có lát thời gian.
  • SCHED_RR giống hệt, nhưng các tiến trình cùng mức ưu tiên chia nhau theo lát thời gian.

Với một tiến trình RT duy nhất, hai cái như nhau. Với nhiều tiến trình RT cùng mức, FIFO để cái đầu tiên chạy mãi.

ionice: ưu tiên đĩa, không phải CPU

nice không ảnh hưởng I/O. Cho việc đó có lệnh riêng:

ionice -c 3 ./sao-luu          # lop idle: chi doc/ghi khi dia ranh
ionice -c 2 -n 7 ./cong-viec   # best-effort, uu tien thap nhat

Nhưng nó chỉ có tác dụng với bộ lập lịch I/O hỗ trợ ưu tiên — bfqcfq cũ. Với mq-deadline hoặc none (mặc định trên nhiều bản Linux hiện đại cho SSD/NVMe), ionice không làm gì cả.

Kiểm trước khi tin:

cat /sys/block/<thiet-bi>/queue/scheduler

Đây là cùng loại bẫy với nice ở phần trước: một lệnh chạy không lỗi, không cảnh báo, và không có tác dụng.

Nhắc lại điều kiện tiên quyết

Mọi con số trong bài này đo với hai tiến trình ghim vào cùng một nhân.

Không ghim, trên máy 16 nhân với chỉ hai tiến trình, cả bốn cách đều cho 50/50 — như đo ở phần 6. Ưu tiên chỉ có nghĩa khi có tranh chấp thật.

Trước khi chỉnh ưu tiên, hãy kiểm r trong vmstat: nhỏ hơn số nhân nghĩa là chưa có gì để tranh, và mọi chỉnh sửa đều vô ích.

Thử ba mươi giây

Xem có tiến trình nào đang chạy ở lớp bất thường không:

ps -eo pid,cls,ni,rtprio,pcpu,comm --sort=-pcpu | head -20

Cột CLS:

Nghĩa
TS CFS thường
IDL SCHED_IDLE
B SCHED_BATCH
FF SCHED_FIFO — thời gian thực
RR SCHED_RR — thời gian thực

Thấy FF hoặc RR ở một tiến trình bạn không cố ý đặt là điều đáng hỏi ngay: nó đứng trên mọi thứ còn lại trên máy, và chỉ có 5% dự phòng của nhân ngăn nó chiếm trọn.

Và với công việc nền, so NI với lớp: NI=19CLS=TS vẫn nhận 1,3%; đổi sang CLS=IDL đưa nó xuống 0,3% mà không mất gì.

Phần sau: ái lực CPU và NUMA — chuyện gì xảy ra khi tiến trình nhảy giữa các lõi.