# sched-ext 研究 * userspace tools and scheduler implementation : [scx](https://github.com/sched-ext/scx) * kernel branch : [sched_ext](https://github.com/sched-ext/sched_ext) ## Building & Setup 若你的電腦作業系統版本是 ubuntu 22.04 ,可以先按照 [sched_ext/.github/workflows/test-kernel.yml](https://github.com/sched-ext/sched_ext/blob/sched_ext/.github/workflows/test-kernel.yml) 的流程安裝試試看,由於我進行實驗的 host machine 是 ubuntu 20.04 focal 版本,許多套件上有衝突或過舊的問題,因此以下採取許多 workaround 。 首先取得原始程式碼 ```shell $ git clone git@github.com:sched-ext/sched_ext.git $ cd sched_ext ``` 接著先利用 `make` 命令搭配參數編譯,不要直接使用 `vng --build` ,它產生的 `.config` 檔案和我們所需的不符合。 產生預設的 `.config` 檔案 ```shell $ make CC=clang-19 LLVM=1 defconfig ``` 接著編輯所需的選項 ```shell $ make CC=clang-19 LLVM=1 menuconfig ``` 要開啟的選項可以參考 [Linux 核心設計: Scheduler(7): sched_ext](https://hackmd.io/@RinHizakura/r1uSVAWwp?fbclid=IwZXh0bgNhZW0CMTAAAR3r72D14vgfxdKVvxpCztPRpBtzGdAgA_oB_WDAfZQudjhDOd-ran8wg-Y_aem_AVMUs6l1Qe_lzPuWSHBPlH63HjsIAflGxftI5wI4zUnYn0suOO6otjtcdy1v5eEV8IVCQ-fjpGUj_X8yNZkK_Q-X#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8-sched_ext) 的設置,特別注意關於 BTF 的選項一定要開啟,否則後續編譯 bpftool 會出錯。 可以透過以下命令觀察 ```shell $ cat .config | grep BTF CONFIG_DEBUG_INFO_BTF=y CONFIG_PAHOLE_HAS_SPLIT_BTF=y CONFIG_DEBUG_INFO_BTF_MODULES=y CONFIG_MODULE_ALLOW_BTF_MISMATCH=y CONFIG_PROBE_EVENTS_BTF_ARGS=y ``` `CONFIG_DEBUG_INFO_BTF=y` 是必要的,其他可以斟酌選取。 到此處如果都沒有問題,就可以編譯核心了 ```shell $ make CC=clang-19 LLVM=1 -j$(nproc) ``` 編譯完成後,我們要來編譯 userspace tool 也就是 scx 專案。首先也是先取得專案程式碼 (不要放在 `/sched_ext` 目錄底下,建議回到家目錄再做 `git clone`) 。 ```shell $ git clone git@github.com:sched-ext/scx.git $ cd scx ``` 應該先參閱 [scx : Build & Install](https://github.com/sched-ext/scx?tab=readme-ov-file#build--install) 來得知需要先安裝的工具,特別注意此處因為我的作業系統版本為 ubuntu 20.04 focal , bpftool 的版本太舊會造成編譯時的問題,因此我先回到 `sched_ext` 目錄底下,編譯新版本的 bpftool 。 ```shell $ make CC=clang-19 -j $(nproc) -C tools/bpf/bpftool/ ``` 接著按照以下命令 ```shell $ meson setup --wipe build -Dkernel_headers=../sched_ext/usr/include --prefix ~ -D bpftool=./../sched_ext/tools/bpf/bpftool/bpftool $ meson compile -C build -j 1 ``` 到此處如果都成功,接下來可以新增一個 shell 的 helper function 如下 ```shell $ sudo vim ~/.bashrc ``` 加入以下這段 ```bash # Helper to test scx scheduler scx() { sudo tmux new-session \; split-window -v \; send-keys -t 0 "$*" Enter } ``` 完成之後可以嘗試利用你編譯的核心來啟動 kvm ```shell $ vng -v -n user --config sched-ext.config --rw ``` 進入虛擬機器之後進行以下測試 ```shell $ cd ../scx $ scx sudo ./build/scheds/rust/scx_rustland/debug/scx_rustland ``` 應該可以看見類似以下的結果 ![image](https://hackmd.io/_uploads/HkloHgrMC.png) 這樣就代表成功執行 scx 了! 另外也可以參考 Righi 大大的部落格 [Getting started with sched-ext development](https://arighi.blogspot.com/2024/04/getting-started-with-sched-ext.html) 。 ## 重現 [Optimizing Scheduler for Linux Gaming](https://ossna2024.sched.com/event/07a5bb414c14ddacb573c147ba5f3435) ### 搭建 sched_ext enabled kernel 於 host machine 由於實驗的重現需要運行 Benchmark ,在虛擬環境當中進行不適合,所以我建構一台基於 ubuntu 24.04 的實體 host machine ,搭配 Nvidia GeForce GTX 1080 顯示卡,並依照 [scx/INSTALL.md/ubuntu](https://github.com/sched-ext/scx/blob/main/INSTALL.md#ubuntu) 之方法使 kernel 支援 scx 。 開機後可以利用以下命令觀察當前 `scx` 服務是否正在運行,預設是 `scx_rustland` 會先運行。 ```shell $ sudo systemctl status scx.service ``` 我們可以透過修改 `/etc/default/scx` 的內容來改變要使用的排程器,例如要使用 `scx_lavd` 的話將 `/etc/default/scx` 進行以下修改 ```diff # List of scx_schedulers: scx_central scx_flatcg scx_lavd scx_layered scx_nest scx_pair scx_qmap scx_rlfifo scx_rustland scx_rusty scx_simple scx_userland -SCX_SCHEDULER=scx_rustland +SCX_SCHEDULER=scx_lavd # Set custom flags for each scheduler, below is an example of how to use #SCX_FLAGS='-s 10000 -n' ``` 之後利用以下命令重啟 `scx` 服務並檢查 `scx` 狀態 ```shell $ sudo systemctl restart scx.service $ sudo systemctl status scx.service ● scx.service - Start scx_scheduler Loaded: loaded (/usr/lib/systemd/system/scx.service; enabled; preset: enab> Active: active (running) since Wed 2024-05-15 09:57:44 CST; 5s ago Main PID: 12051 (scx_lavd) Tasks: 1 (limit: 38278) Memory: 11.5M (peak: 23.4M) CPU: 61ms CGroup: /system.slice/scx.service └─12051 scx_lavd ... ``` ### 安裝 profiling tools 講者使用來做 profiling 的工具主要是 [vapormark](https://github.com/Igalia/vapormark) ,當中量測 FPS 的工具是 [MangoHud](https://github.com/flightlessmango/MangoHud) 要另外安裝。安裝完成之後可以先測試 MangoHud 能否在 Steam 遊戲當中運作並確認 GPU 在系統當中的狀態,之後在 Steam 遊戲的進階設置當中加上 `mangohud %command%` 選項,再開啟遊戲時可以見到以下畫面(我在此處運行的遊戲是 Layers of Fears )。 ![Screenshot from 2024-05-15 14-08-54](https://hackmd.io/_uploads/Sy99Z0Z7C.png) ### 量測實驗比較 利用 Mangohud 與 ginsight 量測並將結果做圖。 #### 開啟 Linux 核心預設排程器 首先將 `scx` 服務關閉,使得系統重新使用預設的排程器。 ```shell $ sudo systemctl disable scx.service Removed "/etc/systemd/system/multi-user.target.wants/scx.service" ``` #### FPS **Linux kernel default** ![lof_result-ginsight-fps-cdf](https://hackmd.io/_uploads/Hk33ukG70.png) ![lof_result-ginsight-fps-ts](https://hackmd.io/_uploads/BJEWYJzm0.png) ![lof_result-ginsight-fps-violin](https://hackmd.io/_uploads/S1yBK1f7C.png) **scx_lavd scheduler** ![scx_lavd-ginsight-fps-cdf](https://hackmd.io/_uploads/r1x3p1z7A.png) ![scx_lavd-ginsight-fps-ts](https://hackmd.io/_uploads/S1L1AJMQA.png) ![scx_lavd-ginsight-fps-violin](https://hackmd.io/_uploads/r1BXCyG7R.png) #### CPU load **Linux kernel default** ![lof_result-ginsight-cpu_load-cdf](https://hackmd.io/_uploads/BJghtJGQ0.png) ![lof_result-ginsight-cpu_load-ts](https://hackmd.io/_uploads/Hkv6t1M70.png) ![lof_result-ginsight-cpu_load-violin](https://hackmd.io/_uploads/r1uAKkGmR.png) **scx_lavd scheduler** ![scx_lavd-ginsight-cpu_load-cdf](https://hackmd.io/_uploads/S1ZoRkfXR.png) ![scx_lavd-ginsight-cpu_load-ts](https://hackmd.io/_uploads/ByC2RkGQA.png) ![scx_lavd-ginsight-cpu_load-violin](https://hackmd.io/_uploads/BySCRkfQC.png) #### GPU load **Linux kernel default** ![lof_result-ginsight-gpu_load-cdf](https://hackmd.io/_uploads/Hy7McyM7C.png) ![lof_result-ginsight-gpu_load-ts](https://hackmd.io/_uploads/Bywm51Gm0.png) ![lof_result-ginsight-gpu_load-violin](https://hackmd.io/_uploads/By3VckMmR.png) **scx_lavd scheduler** ![scx_lavd-ginsight-gpu_load-cdf](https://hackmd.io/_uploads/BySbyxMmA.png) ![scx_lavd-ginsight-gpu_load-ts](https://hackmd.io/_uploads/HJQXJxz7C.png) ![scx_lavd-ginsight-gpu_load-violin](https://hackmd.io/_uploads/rJF4kefmA.png) #### RAM used **Linux kernel default** ![lof_result-ginsight-ram_used-cdf](https://hackmd.io/_uploads/SJ_DckMm0.png) ![lof_result-ginsight-ram_used-ts](https://hackmd.io/_uploads/ByC_q1M7C.png) ![lof_result-ginsight-ram_used-violin](https://hackmd.io/_uploads/Byvq9kzQA.png) **scx_lavd scheduler** ![scx_lavd-ginsight-ram_used-cdf](https://hackmd.io/_uploads/S1UD1xf7A.png) ![scx_lavd-ginsight-ram_used-ts](https://hackmd.io/_uploads/SyKuygf7C.png) ![scx_lavd-ginsight-ram_used-violin](https://hackmd.io/_uploads/rJstyxz7A.png) FPS 的量測結果並不如演講內容所說使用 `scx_lavd` 時會較為平穩,雖然 Low 1% 的數值是 `scx_lavd` 較高,但整體作圖後的結果沒有比較平穩, CPU load 和 GPU load 相較下就有明顯的差異,不管是 CPU 還是 GPU load 在使用 `scx_lavd` 震盪較為明顯。詢問過演講講者 Changwoo Min 後,他的回覆是兩者在處理此遊戲上的性能都已經夠好,但 `scx_lavd` 的 Low 1% FPS 更高是符合預期的,若想看到明顯的差距和遊戲的選擇、電腦性能還有背景是否有其他高負載任務正在執行有關。 我運行另一款遊戲 Left 4 Dead 2 的結果如下 (ubuntu 24.04 上多數 Steam 遊戲都無法運行,只能選擇這些較為老舊的遊戲) 同時在背景播放五個 youtube 影片搭配觀看 nba 直播,以 MangoHud 量測遊戲 FPS 的同時也利用 `schedmon` 紀錄並分析系統排程情況, `scx_lavd` 和預設排程器表現分別如下 #### scx_lavd **FPS** ![scx_lavd_heavy-ginsight-fps-ts](https://hackmd.io/_uploads/By90odV7R.png) ![scx_lavd_heavy-ginsight-fps-cdf](https://hackmd.io/_uploads/Symx2uN7A.png) **CPU load** ![scx_lavd_heavy-ginsight-cpu_load-ts](https://hackmd.io/_uploads/HJ3Mnd470.png) ![scx_lavd_heavy-ginsight-cpu_load-cdf](https://hackmd.io/_uploads/SkqXnOVmA.png) **GPU load** ![scx_lavd_heavy-ginsight-gpu_load-ts](https://hackmd.io/_uploads/r1aH3uVmC.png) ![scx_lavd_heavy-ginsight-gpu_load-cdf](https://hackmd.io/_uploads/BJuI3dVmA.png) #### default_scheduler **FPS** ![default_sched_heavy-ginsight-fps-ts](https://hackmd.io/_uploads/HJIz6uE70.png) ![default_sched_heavy-ginsight-fps-cdf](https://hackmd.io/_uploads/rk_X6dNmA.png) **CPU load** ![default_sched_heavy-ginsight-cpu_load-ts](https://hackmd.io/_uploads/HykHpu47A.png) ![default_sched_heavy-ginsight-cpu_load-cdf](https://hackmd.io/_uploads/Sy6rauN7C.png) **GPU load** ![default_sched_heavy-ginsight-gpu_load-ts](https://hackmd.io/_uploads/By8vauEX0.png) ![default_sched_heavy-ginsight-gpu_load-cdf](https://hackmd.io/_uploads/SkDK6O4mA.png) 分析結果依然是系統預設的排程器 low 1% FPS 更高,此處和講者說的不同,另外使用 `schedmon` 來分析排程器對於不同 task 和整個系統的影響,此分析工具會佔用較久的時間,以下只呈現部分結果,整體圖片太多不適合放在此處。 #### scx_lavd * **system wide task stats data** ![image](https://hackmd.io/_uploads/r1m9RuE7C.png) * **system wide idle stats data** ![image](https://hackmd.io/_uploads/rJQACOVXC.png) * **steam's wait_time, sched_delay, and runtimes** ![image](https://hackmd.io/_uploads/BkqtkFEmC.png) * **IPC:CSteamEngin[7888/7664]'s wait_time, sched_delay, and runtimes** ![image](https://hackmd.io/_uploads/rkUJxtEXR.png) * **Distribution of waiters** ![image](https://hackmd.io/_uploads/S1m3etNQ0.png) * **Distribution of wakers** ![image](https://hackmd.io/_uploads/BJLClKEXR.png) * **40-percentile of waker-waiter** ![image](https://hackmd.io/_uploads/SJFWZFE70.png) #### default_scheduler * **system wide task stats data** ![image](https://hackmd.io/_uploads/B1_tkqN70.png) * **system wide idle stats data** ![image](https://hackmd.io/_uploads/BJli15E70.png) * **steam[4324/0]'s wait_time, sched_delay, and runtimes** ![image](https://hackmd.io/_uploads/HkvxgcEX0.png) * **IPC:CSteamEngin[15020/14894] 's wait_time, sched_delay, and runtimes** ![image](https://hackmd.io/_uploads/H1PrlqVXR.png) * **Distribution of waiters** ![image](https://hackmd.io/_uploads/SkxFx5EX0.png) * **Distribution of wakers** ![image](https://hackmd.io/_uploads/r1Z5ecN7A.png) * **40-percentile of waker-waiter** ![image](https://hackmd.io/_uploads/ByOngqV70.png)