# 開發紀錄 (1): 環境架設
contributed by < [`charliechiou`](https://github.com/charliechiou) > < [`EricccTaiwan`](https://github.com/EricccTaiwan) >
## 關閉 E-core
電腦的 cpu 版本如果有 12-th 後[大小核](https://www.intel.com.tw/content/www/tw/zh/support/articles/000091896/processors.html),會影響到實驗結果,需要把小核關掉
- 查看大小核 (P/E core)
```shell
$ lstopo
```

[二:Intel系列主機板如何關閉CPU部分核心(即E-core)?](https://www.asus.com/hk/support/faq/1054283/#222)

:::spoiler
```$
$ uname -r
6.14.0-16-generic
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 25.04
Release: 25.04
Codename: plucky
```
```shell
$ neofetch
$ lstopo
```
**關閉 E-core 前**
- CPU: 12th Gen Intel i9-12900K (24) @ 5.100GHz


**關閉 E-core 後**
- CPU: 12th Gen Intel i9-12900K (16) @ 5.100GHz


:::
## 版本及 sched_ext 支援
### 核心版本要求
[sched_ext is supported by the upstream kernel starting from version 6.12](https://arighi.blogspot.com/search?updated-max=2025-05-01T00%3A17%3A00%2B02%3A00&max-results=1),因此核心版本要求 6.12+,至於 6.13、6.14 的核心版本在 scx 上的表現是否有差異?
[Tejun Heo](https://github.com/htejun) (scx 的 maintainer) 給了以下回覆,
> There are new features introduced which may improve performance in some cases (e.g. queued_wakeup support) but for the most part, the kernel versions wouldn't cause noticeable differences. All schedulers should work fine across the kernel versions.
[name=Tejun Heo]
### 開發環境的核心及 Ubuntu 版本
> 我們將 server 從 Ubuntu 24.04 $\to$ 24.10 $\to$ 25.04 一路向上升級; 如果空間有限,也可用舊版 Ubuntu 搭配 kernel v6.12+ 作為實驗環境 (e.g. Ubuntu 24.04 w/ kernel v6.12)
```shell
OS: Ubuntu 25.04 x86_64
Kernel: 6.14.0-16-generic
```
#### 方法一 : 升級至 Ubuntu 25.04
```shell
$ sudo apt update
$ sudo apt upgrade
$ sudo apt dist-upgrade
$ sudo apt install update-manager-core
```
目前最新的 LTS 為 Ubuntu 24.04,因此需調整升級設定以對應此版本:
```shell
$ sudo vim /etc/update-manager/release-upgrades
```
把最後一列的 `Prompt=lts` 改成 `Prompt=normal`,
```diff
[DEFAULT]
# Default prompting and upgrade behavior, valid options:
#
# never - Never check for, or allow upgrading to, a new release.
# normal - Check to see if a new release is available. If more than one new
# release is found, the release upgrader will attempt to upgrade to
# the supported release that immediately succeeds the
# currently-running release.
# lts - Check to see if a new LTS release is available. The upgrader
# will attempt to upgrade to the first LTS release available after
# the currently-running one. Note that if this option is used and
# the currently-running release is not itself an LTS release the
# upgrader will assume prompt was meant to be normal.
- Prompt=lts
+ Prompt=normal
```
接著執行
```shell
$ sudo do-release-upgrade -d # 開始升級 Ubuntu
```
升級後檢查是否升級成功
```shell
$ lsb_release -a
```
由於每次升級僅能跨一個版本,因此若從 24.04 升級至 25.04,需先升級至 24.10,再進一步升級至 25.04,共需進行兩次升級。
#### 方法二 : 僅下載 kernel v6.12
先下載對應的核心檔案
```shell
$ wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.12.tar.xz
$ tar -xf linux-6.12.tar.xz
$ cd linux-6.12
```
接著把原本作業系統中的設定檔複製並編譯
```shell
$ cp /boot/config-$(uname -r) .config
$ make menuconfig
```
編譯核心(可能會花上很多時間)
```shell
$ make -j$(nproc)
$ sudo make modules_install
$ sudo make install
```
最後更新 grub 並重開機。
```shell
$ sudo update-grub
$ sudo reboot
```
確認升級後的核心版本
```shell
$ uname -r # 要出現 6.12
```
### 確認支援 sched_ext
確認目前核心是否支援 sched_ext
```shell
$ ls /sys/kernel/ | grep sched_ext
```
確認目前 sched_ext 的狀態
```shell
$ cat /sys/kernel/sched_ext/state
```
以 `scx_rustland` 為例(後續會提到如何編譯 `scx_rustland` 並執行)執行 `scx_rustland` 前後輸出結果如下:
```shell
$ # Before attached scx_rustland
$ cat /sys/kernel/sched_ext/state
disabled
$ # After attached scx_rustland
$ cat /sys/kernel/sched_ext/state
enabled
```
### 下載 sched-ext (簡稱 scx)
> [sched-ext/scx: README](https://github.com/sched-ext/scx?tab=readme-ov-file#sched_ext-schedulers-and-tools)
可以參考 [Build & Install](https://github.com/sched-ext/scx?tab=readme-ov-file#build--install),下方以 Ubuntu/Debian 環境為例
#### 1. 下載 `meson`
> Note: Many distros only have earlier versions of meson, in that case just clone the meson repo and call `meson.py`
> e.g. `/path/to/meson/repo/meson.py compile -C build` .
>
> Alternatively, use pip e.g. `pip install meson` or `pip install meson --break-system-packages` (if needed).
#### 2. 下載 dependencies
```shell
$ sudo apt install build-essential libssl-dev llvm lld libelf-dev meson cargo rustc clang llvm cmake pkg-config protobuf-compiler
```
#### 3. Static linking against libbpf (preferred)
> 這個方式,C 和 Rust 都可以編譯完成
```shell
$ cd ~/scx
$ meson setup build --prefix ~
$ # 以下每次更新 code 完都需要重跑 (編譯前記得存檔)
$ meson compile -C build
$ sudo meson install -C build
$ #
$ meson setup --wipe build ## re-config 才需要或是 build 失敗
```
> meson always uses a separate build directory. Running the following commands in the root of the tree builds and installs all schedulers under `~/bin`.
執行 meson compile 後會把執行檔及中間的建構檔存在對應的資料夾中,若要把可執行的檔案安裝下來則需要使用 meson install 並透過 `-C` 切換到 build 的資料夾中做安裝,而安裝的位置則是前述用 setup 設定的位置 (i.e., `~`)。
接著執行 `sudo ~/bin/<schedule name>` 便可執行對應的 scheduler。
>詳細的安裝步驟可以查看 `meson.build` 的腳本,其中在 `if enable_rust` 的段落中
>```rust
> cargo_cmd = [cargo, 'build', '--manifest-path=@INPUT@', '--target->dir=@OUTDIR@', cargo_build_args]
>```
>會把 rust 的排程器建構在 `@OUTDIR@` ,而 `@OUTDIR@` 則是由 meson 傳入的 target。 因此也可以在 target 資料夾中的 `release-fast` 中找到我們的 rust 排程器。 另一方面 c 語言所建構的排程器則會安置在 build 資料夾底下。
## 工具介紹
### scxtop
```shell
$ sudo LC_ALL=C scxtop # 執行 scxtop
```
會出現下方的 TUI 界面,按下 `q` 即可離開

執行 scx 排程器的過程中,按下 `a` 可以儲存 trace 檔案,接著打開 [Perfetto UI](https://ui.perfetto.dev/#!/viewer) ,點選左側的 `Open trace file` 開啟剛剛生成的檔案,便可看到下圖的 CPU 排程結果。

若不想使用到 `scxtop` 提供的 TUI 介面,也可以利用以下指令生成檔名為 test 的二進制檔
```shell
$ sudo scxtop trace --trace-ms 5000 --output-file test
```
### Perfetto

詳細的測試分析,可見[開發紀錄 (2): FIFO/RR scheduler](https://hackmd.io/@cce-underdogs/linux-exp2),這邊只介紹幾個重要的參數,同時也是我們踩過的地雷,
- [Wall duration](https://blog.csdn.net/f2006116/article/details/107581327) (ms)
- 代表一個 Process 的總共持續時間
- Wall Avg duration (ms)
- :::warning
[代表一個 Process 在被中斷前的平均持續時間,而不是平均的 time slice。](https://hackmd.io/@cce-underdogs/prob-1#Clarification) (這點很重要!!!)
:::
- Occurences
- Process 執行期間的中斷次數
<!-- ### Perf
參考:[GNU/Linux 開發工具 - 運用 Perf 分析程式效能並改善](https://hackmd.io/@sysprog/gnu-linux-dev/https%3A%2F%2Fhackmd.io%2F%40sysprog%2Flinux-perf)
使用以下指令確認目前 perf 權限
```shell
$ cat /proc/sys/kernel/perf_event_paranoid
```
若需要修改設定,可藉由以下命令調整:
```
$ sudo sysctl kernel.perf_event_paranoid=<parameter>
```
該參數的權限值共有四種設定,分別如下:
- `2`:不允許執行任何效能量測。但某些用於查看或分析現有紀錄的命令仍然可使用,例如 perf ls, perf report, perf timechart, perf trace
- `1`:不允許取得 CPU 事件資料 (CPU events data),但可用 perf stat, perf record 並取得 Kernel profiling 資料
- `0`:不允許存取原始 tracepoint,但可使用 perf stat、perf record 並取得 CPU 事件資料。
- `-1`:開放所有權限,無限制
可以用下列的指令來錄下排程並顯示。
```shell
$ perf sched record
$ perf sched timehist -Vw --state
``` -->
## Ref
* [Linux 核心專題: CPU 排程器 by vax-r](https://hackmd.io/@sysprog/BJdyxvxX0)
* [Linux 核心專題: sched_ext 研究 by otteryc](https://hackmd.io/@sysprog/H1u6D9LI0)
* [arighi's blog - Ubuntu 25.04 is now sched_ext ready](https://arighi.blogspot.com/)
* [sched-ext/scx](https://github.com/sched-ext/scx)
* [eBPF 隨筆(七):sched_ext](https://medium.com/@ianchen0119/ebpf-%E9%9A%A8%E7%AD%86-%E4%B8%83-sched-ext-f7b60ea28976)
* [Perfetto Docs](https://perfetto.dev/docs/)
* [課程討論區相關文章](https://www.facebook.com/share/p/19MQee4kSX/)
<!--
## FB 好文
:::spoiler 貼文
原文連結 : https://www.facebook.com/share/p/19MQee4kSX/
或許有人會好奇,跟其他 Linux 核心課程相比,為何開設在成功大學的「Linux 核心設計」重視數學 (例如在課堂要求學員證明級數收斂、解釋泊松分布),甚至有人誤以為授課教師在刁難,但真相是,任何工程議題走到極致後,都會通往數學,而 Linux 核心本身就是多種工程議題的彙整,當然更容易接觸到數學。
以 Linux 核心的 CPU 排程器來說,考慮到雲端運算的需求,CFS 發展一系列 CPU 頻寬控制 (bandwidth control; BWC) 的機制,而這背後就是機率統計、排隊理論所支撐。引述內文:
>That is, suppose we have 2 tasks, both specify a p(95) value, then we have a p(95)\*p(95) = 90.25% chance both tasks are within their quota and everything is good. At the same time we have a p(5)p(5) = 0.25% chance both tasks will exceed their quota at the same time (guaranteed deadline fail). Somewhere in between there’s a threshold where one exceeds and the other doesn’t underrun enough to compensate; this depends on the specific CDFs.
Linux 核心的 CPU 排程器負責在多個競爭行程間分配處理器時間,其設計目標涵蓋 fairness、效率與回應性。此處 fairness 指在時間尺度上,將處理器時間依比例分配給所有可執行 (runnable) 行程,使其長期累積的運算時間趨近於預期占比。
為實施資源限制,核心引入 CPU 頻寬控制 (BWC) 機制,允許系統管理員為 cgroup 設定明確的 CPU 使用上限。其運作依賴二項參數:每週期允許使用的 CPU 配額 cpu.cfs_quota_us 與週期長度 cpu.cfs_period_us。當某個 cgroup 在一個週期內耗盡配額,該群組內所有行程即會暫停執行,直至下一週期重新取得配額。此機制具確定性,能強制執行所設資源約束。
然而,單靠此類確定性機制,難以充分發揮處理器效能,特別是在行程執行時間變異性高的情況下。此時,排程器設計便與機率統計理論密切相關。實際上,Linux 的 CFS 等現代排程器,普遍內建統計推論機制。排程器透過蒐集歷史執行紀錄,運用指數加權移動平均 (EWMA) 預測未來負載,同時在長期觀察中評估 fairness 是否達成,即各行程獲得的處理時間比例是否合理。
系統中充斥各類隨機事件,例如 I/O 完成、中斷觸發等,排程器需在此等不確定情境下維持反應性與穩定性。
為克服傳統 BWC 帶來的過度保守問題,Linux 排程機制進一步引入具彈性的 Burst (突發) 特性,展現統計導向的設計思想。觀察顯示,行程實際執行時間大多低於其最壞情況執行時間 (Worst-Case Execution Time, WCET)。傳統即時系統分析(如基於 EDF 的可行性檢驗)以 WCET 為保證條件,導致保守的資源預留與低效的資源使用。
Burst 策略主張改以統計分佈描述行程行為,選用第 95 百分位(或其他分位數)所對應的執行時間 $x$ 作為常態配額,取代極端的 $x + e$(即 WCET)。此方式使總體利用率 $\sum x_i / \text{Period}_i$ 降低,可納入更多行程。系統容許行程短期內超過 $x$ 執行(即動用額外額度 $e$),並仰賴其未來執行時間低於 $x$ 以抵銷超額。
此策略不再強求所有截止期限均被滿足。當多個行程同時超出 $x$ 時,系統總需求可能超過處理器上限,導致部分行程逾期。不過,若 $x$ 設定不低於平均執行時間,系統平均負載仍可穩定控制。即使發生逾期,其延遲(tardiness)可受限於總彈性額度 $\sum e_i$,只要 WCET 評估具保守性,便能確保長期行為不發散。
評估 Burst 帶來的實際干擾,特別是對其他使用者的影響,屬於複雜問題。系統中同時存在多使用者、彈性借貸與隨機需求分佈,使傳統工具 (如排隊理論與馬可夫鏈) 難以建構有效模型,因此 Linux 核心開發者轉而採用模擬方法分析其行為。
模擬中,研究者設定 $m$ 個 cgroup 共享 CPU 資源,每組配有相同常態配額與變動大小的 Burst Buffer (以配額倍數 $b$ 表示),平均 CPU 利用率 $u_{avg}$ 為主要參數。各 cgroup 的需求建模為獨立同分佈隨機變數,分佈型態包括指數、泊松與帕累托 (Pareto) 分佈,其中帕累托因其重尾性,適合模擬突發性極高的負載情形。
模擬紀錄兩項指標:違反 WCET 的機率 $P(\text{WCET} > 1)$,即系統在單一週期內無法滿足所有需求的機率;連續違約週期的期望值 $E(\text{WCET})$,即從第一次逾期至恢復正常的週期數。
結果揭示若干趨勢:干擾程度對 $u_{avg}$ 與群組數 $m$ 敏感度極高。在高利用率情境下,系統缺乏彈性緩衝以吸收突發需求,錯誤率顯著提升。若群組數偏少,單一群組的高需求即可能造成過載;反之,群組數多時,各自需求波動彼此抵銷,總體變異性降低,系統更為穩定。相較之下,Burst Buffer 大小 $b$ 的影響較小,特別在低 $u_{avg}$ 或高 $m$ 條件下影響更為微弱。不同分佈型態亦顯著影響行為,帕累托分佈因重尾特性,在高負載下易引發明顯干擾。
據此可提出若干建議:在高負載或僅有少數關鍵群組的系統中,應避免或嚴格限制 Burst Buffer 的使用;而在群組眾多且平均利用率較低的環境下,可適度啟用甚至放寬 Burst Buffer 設定,在不顯著增加風險的前提下提升資源使用效率。
於是,從確定性的 BWC 到統計驅動的 Burst 特性,Linux 排程機制體現對資源效率與可預測性之間微妙平衡的追求。理解 fairness 的技術意涵、掌握機率統計理論並配合模擬方法進行驗證,是發展現代穩健排程策略的關鍵。
https://docs.kernel.org/scheduler/sched-bwc.html
:::
-->