Điều chỉnh scheduler Linux ở userspace: sched_ext, BPF và lý do Meta chuyển sang dùng¶
sched_ext cho phép thay chính sách lập lịch CPU của Linux bằng một chương trình BPF, nạp và gỡ ngay khi máy đang chạy. Bài này giải thích nó thay đổi điều gì, ai đang dùng và đáng thử ở đâu.
Một scheduler cho mọi workload¶
Scheduler (bộ lập lịch CPU) là thành phần của kernel quyết định task nào được chạy, trên CPU nào và trong bao lâu. Mỗi khi một task thức dậy, chờ I/O hay dùng hết time slice, scheduler lại phải đưa ra lựa chọn đó, hàng nghìn lần mỗi giây.
Scheduler mặc định của Linux (EEVDF, viết tắt của Earliest Eligible Virtual Deadline First) được thiết kế để phục vụ tốt mọi loại workload. Tuy nhiên, một thiết kế đa dụng hiếm khi là tối ưu cho một workload cụ thể. EEVDF được đưa vào từ Linux 6.6, thay thế CFS (Completely Fair Scheduler), scheduler mặc định của Linux từ năm 2007.
Phần mềm gNodeB là một ví dụ điển hình: data plane DPDK, control plane, M-plane, logging và nhiều tiến trình nền cùng chia sẻ tài nguyên CPU. Mỗi nhóm tác vụ có yêu cầu riêng về độ trễ, khả năng tận dụng cache và cách phân bổ core.
Trước đây, việc thay đổi chính sách lập lịch đòi hỏi vá kernel, build lại, khởi động lại hệ thống và duy trì bản vá qua mỗi lần nâng cấp kernel. Từ Linux 6.12, đã có một cách tiếp cận khác: sched_ext.
sched_ext là gì¶
sched_ext là một scheduler class trong kernel, cho phép viết chính sách lập lịch bằng chương trình BPF. Chương trình đó được nạp và gỡ ngay khi hệ thống đang chạy, tương tự việc khởi chạy và dừng một ứng dụng. Tính năng có trong kernel mainline từ Linux 6.12.
Bên cạnh phần kernel, repo sched-ext/scx chứa 16 scheduler viết sẵn (phần userspace bằng Rust) cùng thư viện và công cụ hỗ trợ. Để sử dụng, chỉ cần một kernel hỗ trợ sched_ext và chạy binary của scheduler tương ứng.
Repo scx là dự án đồng hành chính thức của sched_ext, thuộc tổ chức sched-ext trên GitHub. Nhóm khởi xướng gồm các kỹ sư Meta và Google; trong đó Tejun Heo cũng là người gửi các bản cập nhật sched_ext vào kernel mainline. Vai trò được phân chia rõ ràng: kernel chứa framework cùng vài scheduler ví dụ bằng C trong tools/sched_ext, còn scx chứa các scheduler dùng trong thực tế, thư viện dùng chung và công cụ đóng gói.
Đây cũng là nơi phát triển scx_lavd (Igalia, tài trợ bởi Valve) và các scheduler mà Meta triển khai trong production. Repo phát hành theo giấy phép GPL-2.0, có gần 9.000 commit, và được các distro như Arch, openSUSE, Fedora đóng gói sẵn. Động cơ thiết kế được nhóm tác giả trình bày trong OVERVIEW.md.
Hành trình và hiện trạng¶
Từ bản RFC đầu tiên đến khi vào mainline mất gần hai năm; từ 2025, sched_ext phát triển nhanh với tính năng mới ở hầu hết các bản kernel.
Hình 1. Các mốc chính của sched_ext, 11/2022 đến 10/2026.
Quá trình đưa vào mainline gặp nhiều tranh luận: đề xuất vấp phải phản đối từ maintainer scheduler, và cuối cùng Linus Torvalds quyết định merge. Kế hoạch ban đầu là Linux 6.11 nhưng không kịp; sched_ext chính thức vào Linux 6.12 (9/2024), cùng đợt với PREEMPT_RT.
Mốc đáng chú ý nhất gần đây là Linux 7.3: sub-scheduler cho phép gắn nhiều BPF scheduler vào cây cgroup, mỗi miền ứng dụng một scheduler riêng. Ubuntu 26.10 chạy trên kernel này.
Hiện trạng (11/2026):
- 16 scheduler trong repo scx, khoảng 2.200 sao trên GitHub.
- Có gói hoặc hướng dẫn cài cho Ubuntu, Arch, Fedora, openSUSE, Gentoo và Nix.
- Dự án vẫn đang trong giai đoạn hoàn thiện: cuối 10/2026 có CVE-2026-99105, sửa một lỗi stall trong sched_ext.
Những gì thay đổi và những gì giữ nguyên¶
sched_ext thay chính sách lập lịch, không viết lại scheduler. Kernel vẫn đảm nhận context switch, runqueue và các lớp RT; người viết chỉ quyết định task nào chạy, chạy trên CPU nào và trong bao lâu.
Hình 2. Kiến trúc phân lớp của một scheduler sched_ext.
Hai lớp trên là phần thay được: một chương trình BPF chứa chính sách, đi kèm một chương trình userspace để nạp, theo dõi và đôi khi tham gia ra quyết định. Hai lớp dưới là kernel, không đổi. Khi scheduler bị gỡ, mọi task quay về EEVDF. Chi tiết về hàng đợi DSQ và các callback sẽ nằm trong một technote riêng.
Vì sao đáng quan tâm¶
sched_ext mang lại ba lợi ích mà việc sửa trực tiếp scheduler trong kernel khó đạt được:
- Thử nghiệm nhanh: chu trình sửa, build, chạy và đo diễn ra trong vài phút, không cần khởi động lại hay chờ chu kỳ phát hành kernel.
- Tùy biến theo ứng dụng: chính sách có thể dùng hiểu biết riêng về workload, điều mà scheduler đa dụng không thể giả định.
- Triển khai nóng: thay scheduler trên máy đang chạy production, rollback chỉ bằng cách dừng process.
Hình 3. Vòng thử nghiệm chính sách lập lịch: cách truyền thống so với sched_ext.
Hai bước tốn kém nhất của cách truyền thống, build lại kernel và reboot, không còn nằm trong vòng lặp của sched_ext.
Ai đang sử dụng sched_ext¶
Meta là đơn vị triển khai sched_ext lớn nhất từng được công bố, theo hai cách: một scheduler chuyên biệt cho dịch vụ quảng cáo và một scheduler đa dụng làm mặc định cho fleet server.
Dịch vụ quảng cáo (Ads). Hệ thống phân phối quảng cáo của Meta xử lý trung bình hơn 5 triệu request mỗi giây. Khi nâng kernel từ 6.4 lên 6.9, EEVDF gây suy giảm độ trễ, buộc một phần máy chủ Ads phải ở lại kernel cũ. Meta viết một chính sách riêng trên sched_ext: chia mềm CPU thành hai nhóm, một cho các thread trên đường xử lý request nhạy độ trễ, một cho phần việc còn lại, với kích thước mỗi nhóm điều chỉnh theo tải.
Kết quả lần triển khai đầu trên dòng máy chủ Ads lớn nhất (AMD Bergamo):
| Chỉ số | Kết quả |
|---|---|
| Độ trễ p99 ở giai đoạn truy xuất quảng cáo | Giảm 28% |
| Số quảng cáo được xếp hạng (có trọng số) | Tăng 1,1% |
| Điện năng tiết kiệm trên toàn fleet | 3,28 MW |
Hai lần cập nhật chính sách sau đó chỉ thay đổi ở userspace, được triển khai trong vài ngày thay vì vài tháng, và giảm thêm 60% độ trễ p99 cùng 18% lỗi timeout trên đường xử lý chính.
Scheduler mặc định cho fleet. Tại Linux Plumbers Conference 12/2025 ở Tokyo, kỹ sư Meta trình bày việc dùng scx_lavd làm scheduler mặc định cho các server không cần chính sách chuyên biệt, và gọi đây là scheduler mặc định mới của Meta. scx_lavd vốn được Igalia phát triển theo hợp đồng với Valve cho máy chơi game cầm tay Steam Deck. Lập luận được đưa ra là game và data center có chung một rủi ro: trễ deadline, với game là mất khung hình, với server là request chậm và vi phạm SLO. Meta ghi nhận lavd hoạt động tốt trên nhiều cấu hình CPU và bộ nhớ, đồng thời cân tải tốt qua ranh giới CCX/LLC.
Ngoài Meta. scx_lavd được dùng trong các bản phân phối Linux thiên về gaming như CachyOS Handheld Edition và Bazzite. Theo README của dự án, Google cũng cam kết đầy đủ với sched_ext.
An toàn khi vận hành¶
Câu hỏi thường gặp đầu tiên là việc nạp code vào scheduler có thể làm hệ thống sập hay không. sched_ext được thiết kế để ngăn điều đó bằng ba cơ chế:
- Chương trình BPF được kiểm tra trước khi nạp, nên các lỗi như truy cập bộ nhớ sai hay vòng lặp vô hạn bị chặn ngay từ đầu.
- Nếu scheduler bỏ đói một task quá lâu, kernel tự gỡ nó và đưa mọi task về scheduler mặc định.
- Có thể tắt scheduler bằng cách dừng process (Ctrl-C) hoặc dùng SysRq-S; hệ thống tiếp tục chạy bình thường với EEVDF.
Theo tài liệu dự án, nếu bỏ qua bug của chính kernel, trường hợp xấu nhất là một số task bị đói cho đến khi watchdog kích hoạt. Điều không được đảm bảo là hiệu năng: một scheduler thiết kế chưa tốt vẫn có thể chậm hơn scheduler mặc định đáng kể. Cơ chế chi tiết sẽ nằm trong technote.
Các scheduler có sẵn¶
Repo scx hiện có 16 scheduler; năm scheduler dưới đây là điểm khởi đầu tốt để tìm hiểu.
| Scheduler | Dùng cho việc gì | Điểm đặc trưng |
|---|---|---|
| scx_lavd | Tác vụ nhạy độ trễ; mặc định cho fleet server của Meta | Ra đời cho Steam Deck, ưu tiên task theo mức độ nhạy trễ |
| scx_layered | Phân vùng workload theo cấu hình | Chia task thành các "layer", mỗi layer một chính sách; cần tinh chỉnh |
| scx_rusty | Máy nhiều socket, NUMA | Lập lịch đơn giản trong BPF, cân tải ở userspace |
| scx_bpfland | Dùng chung cho desktop và server | Nhận biết topology CPU |
| scx_rustland | Học và thử nghiệm | Hầu hết quyết định nằm ở userspace Rust |
Tiêu biểu: scx_lavd khác EEVDF ở đâu¶
Khác biệt cốt lõi của scx_lavd là nó tự suy ra task nào cần độ trễ thấp từ hành vi lúc chạy, thay vì dựa vào thông tin ứng dụng khai báo. scx_lavd (Latency-criticality Aware Virtual Deadline) được chọn làm ví dụ vì nó vừa chạy trên Steam Deck, vừa là scheduler mặc định cho fleet server của Meta.
EEVDF phân chia CPU công bằng theo trọng số: mỗi task nhận phần CPU tương ứng với giá trị nice, và task nào đang được ít hơn phần của mình sẽ được ưu tiên. Muốn một task có độ trễ thấp hơn, ứng dụng hoặc quản trị viên phải tự điều chỉnh nice hay các tham số lập lịch.
scx_lavd quan sát từng task và tính một điểm "mức độ nhạy trễ" (latency criticality) từ các tín hiệu sau:
- Tần suất chờ: task thường xuyên block để chờ I/O hay đồng bộ là dấu hiệu của bên tiêu thụ trong một pipeline.
- Tần suất đánh thức task khác: task thường xuyên đánh thức task khác là dấu hiệu của bên sản xuất.
- Thời gian chạy ngắn: task chỉ chạy những đợt ngắn rồi nhường CPU thường là task tương tác.
- Quan hệ đánh thức: mức độ nhạy trễ được lan truyền một phần giữa task đánh thức và task được đánh thức, nên cả chuỗi xử lý cùng được ưu tiên.
Task vừa chờ nhiều vừa đánh thức nhiều thường nằm giữa một chuỗi xử lý, ví dụ compositor nhận input rồi đánh thức renderer. Điểm này được dùng để tính virtual deadline: task nhạy trễ có deadline sớm hơn nên được chạy trước, trong khi hình phạt công bằng vẫn ngăn task khác bị bỏ đói.
Hình 4. Cách scx_lavd đánh giá mức nhạy trễ trong một chuỗi task.
Compositor vừa chờ input vừa đánh thức renderer nên được xếp mức nhạy trễ cao nhất; tác vụ nền chạy dài thì nhường chỗ, dù với EEVDF cả bốn được đối xử như nhau.
| Khía cạnh | EEVDF (mặc định) | scx_lavd |
|---|---|---|
| Cách xác định task cần độ trễ thấp | Dựa vào nice và tham số do ứng dụng đặt | Tự suy ra từ hành vi lúc chạy |
| Thông tin dùng để xếp lịch | Phần CPU đã nhận so với phần công bằng | Tần suất chờ, tần suất đánh thức, thời gian chạy, quan hệ giữa các task |
| Chuỗi task phụ thuộc nhau | Không xét riêng | Lan truyền mức ưu tiên dọc theo chuỗi |
| Năng lượng | Do các cơ chế khác của kernel đảm nhận | Tích hợp core compaction: gom tải vào ít core hơn, có chế độ tự động chọn giữa hiệu năng và tiết kiệm điện |
| Topology CPU | Cân tải theo các scheduling domain của kernel | Chia CPU thành các miền tính toán, ưu tiên core tần số cao, cân tải qua ranh giới LLC |
Điểm đáng chú ý là scx_lavd không cần cấu hình theo từng workload. Đây cũng là lý do Meta chọn nó làm mặc định: một scheduler tự thích nghi với nhiều loại máy và dịch vụ, thay vì phải viết chính sách riêng cho từng nơi. Thiết kế bên trong các scheduler còn lại sẽ để dành cho technote.
Ý nghĩa đối với team¶
sched_ext chưa phải công cụ cho data plane, nhưng đáng để thử nghiệm với phần còn lại của hệ thống. Có hai điều kiện cần lưu ý:
- Kernel ≥ 6.12. BSP cho các nền tảng nhúng (LX2160A, ZynqMP) thường dùng kernel cũ hơn, nên điểm thử nghiệm hợp lý nhất là server x86.
- Không ảnh hưởng đến task RT. sched_ext chỉ điều phối task thường (SCHED_NORMAL, SCHED_BATCH, SCHED_IDLE). Thread SCHED_FIFO và SCHED_DEADLINE, như các core DPDK hay thread RT, vẫn do kernel quản lý như trước.
Một số hướng đáng thử, tất cả cần kiểm chứng trên máy thật:
- Điều phối các thread non-RT quanh data plane (control plane, M-plane, logging) nhằm đánh giá khả năng giảm nhiễu lên các core RT.
- Dùng sub-scheduler theo cgroup (từ Linux 7.3) để mỗi nhóm dịch vụ có chính sách riêng.
- Thử các chính sách gom tải lên ít core, như một hướng bổ sung cho bài toán tiết kiệm năng lượng.
Kết luận¶
sched_ext biến chính sách lập lịch thành một thành phần có thể thử nghiệm, đo đạc và thay thế trong vài phút thay vì vài tháng.
Tài liệu đọc thêm¶
- OVERVIEW.md: động cơ thiết kế từ nhóm tác giả
- Changwoo Min: sched_ext Part 1 và Part 2
- Andrea Righi: Getting started with sched_ext development
Nguồn¶
- GitHub: sched-ext/scx
- Kernel docs: Extensible Scheduler Class
- LKML: RFC patchset (11/2022)
- LWN: Extensible scheduler class to be merged
- Phoronix: sched_ext merged for Linux 6.12
- Phoronix: Meta dùng scheduler của Steam Deck
- Meta Engineering: Ads service với sched_ext
- Phoronix: sched_ext được tái cấu trúc (Linux 7.2)
- Phoronix: sub-scheduler hoàn thiện trong Linux 7.3
- LPC 2026: sched_ext Microconference
- CVE-2026-99105