最近一直在弄 TiKV 的性能優化,想到是否系統的 scheduler 會影響 TiKV 的性能,于是就稍微研究了下 perf sched。
首先抓取一段時間的記錄,使用
sudo perf sched record -- sleep 5
這里需要注意,sched 會記錄非常多的信息,所以時間不能很長,我上面就是記錄了 5 秒,大概生成了快 400 MB 的數據。
然后使用 latency 命令來看最大的 delay:
sudo perf sched latency -s max
-----------------------------------------------------------------------------------------------------------------
Task | Runtime ms | Switches | Average delay ms | Maximum delay ms | Maximum delay at |
-----------------------------------------------------------------------------------------------------------------
grpc-poll-2:(3) | 10162.378 ms | 83270 | avg: 0.019 ms | max: 2.346 ms | max at: 2600393.062326 s
grpc-poll-1:(3) | 11509.903 ms | 68917 | avg: 0.018 ms | max: 2.208 ms | max at: 2600394.231449 s
grpc-poll-0:(3) | 12253.333 ms | 53227 | avg: 0.020 ms | max: 2.024 ms | max at: 2600391.721447 s
可以看到,我們最大的 delay 是 gRPC 線程的 2.346 ms,在 2600393.062326 s 這個時間點,可以通過 script 命令詳細的找到相應的地方。下面只是一個簡單的 script 例子:
sudo perf sched script
raftstore-5 91697 [017] 2587136.922586: sched:sched_wakeup: apply_worker_2:91706 [120] success=1 CPU:019
raftstore-5 91697 [017] 2587136.922586: sched:sched_wakeup: apply_worker_2:91706 [120] success=1 CPU:019
:91649 91649 [008] 2587136.922610: sched:sched_wakeup: grpc-poll-0:91709 [120] success=1 CPU:006
:91649 91649 [008] 2587136.922670: sched:sched_wakeup: grpc-poll-0:91709 [120] success=1 CPU:006
raftstore-5 91697 [017] 2587136.922705: sched:sched_wakeup: apply_worker_1:91705 [120] success=1 CPU:031
我們也可以通過 map 命令詳細的知道每個 CPU 任務的運行狀態以及切換情況:
sudo perf sched map
B0 U0 Y0 A0 . B1 S0 J0 Q0 . E0 C0 A1 . Z0 . . W0 *C1 M0 G0 L0 R0 N0 2600390.841419 secs C1 => raftstore-5:91697
B0 U0 *. A0 . B1 S0 J0 Q0 . E0 C0 A1 . Z0 . . W0 C1 M0 G0 L0 R0 N0 2600390.841423 secs
B0 U0 . A0 . B1 S0 J0 Q0 . E0 *. A1 . Z0 . . W0 C1 M0 G0 L0 R0 N0 2600390.841432 secs
B0 U0 . A0 . B1 S0 J0 Q0 . E0 . A1 . Z0 . . W0 C1 M0 *. L0 R0 N0 2600390.841436 secs
B0 U0 . A0 . B1 S0 J0 Q0 . E0 . A1 . Z0 *K0 . W0 C1 M0 . L0 R0 N0 2600390.841437 secs
B0 U0 . *. . B1 S0 J0 Q0 . E0 . A1 . Z0 K0 . W0 C1 M0 . L0 R0 N0 2600390.841438 secs
上面每一行表示的是當前時間點所有 CPU 執行任務的情況, A0,C1 表示的是執行的任務,而 .
則是表明空閑,*C1
這個表明發生了切換,切到了任務 C1 上面。上面可以發現幾乎所有 CPU 都在處理任務。
因為我們并沒有安裝最新的內核,所以并沒有 perf sched 的 timehist 命令,也就沒法嘗試了。另外,perf sched 還有一個 replay 命令,會根據采集到的數據回放,便于排查問題。
上面僅僅是對 perf sched 的簡單使用,可以知道,我們最大的 delay 是 2 ms,那么,能不能減少呢?
因為我們通常使用的都是 CFS 調度,有幾個指標可以關注:
-
sched_min_granularity_ns
:任務最小運行時間,防止頻繁的切換 -
sched_wakeup_granularity_ns
:該值只是用來判斷任務被喚醒后能否搶占當前任務。 -
sched_latency_ns
:CFQ 隊列所有任務的運行一次的周期。如果任務數量超過了sched_latency_ns / sched_min_granularity_ns
,周期就是number_of_running_tasks * sched_min_granularity_ns
。
對于我們系統來說,這三個值如下:
kernel.sched_min_granularity_ns = 3000000
kernel.sched_latency_ns = 24000000
kernel.sched_wakeup_granularity_ns = 4000000
看起來有點大,參考網上的一些實現調整下:
kernel.sched_min_granularity_ns = 100000
kernel.sched_wakeup_granularity_ns = 25000
kernel.sched_latency_ns = 1000000
繼續測試,發現性能沒啥太大的變化,而且 perf sched record 發現最大的 latency 也跟之前差不多。具體原因,我因為還不熟悉內核,所以也就考慮放一放,后面在請教大牛。但這里我知道,這個調整雖然在我測試這邊沒發現太大的作用,但至少學會了通過 sched 來排查系統的問題,這個沒準以后能在其他的地方用到。