linuxのfull ticklessを試してみた

19
LinuxのFull tickless を試してみた 第九回カーネル/VM探検隊 Hiraku Toyooka (@hiraku_wfs)

Upload: hiraku-toyooka

Post on 07-Nov-2014

4.519 views

Category:

Technology


12 download

DESCRIPTION

第九回カーネル/VM探検隊での発表スライド

TRANSCRIPT

Page 1: LinuxのFull ticklessを試してみた

LinuxのFull ticklessを試してみた第九回カーネル/VM探検隊

Hiraku Toyooka (@hiraku_wfs)

Page 2: LinuxのFull ticklessを試してみた

自己紹介

• 豊岡 拓(とよおか ひらく)

• Twitter: @hiraku_wfs

• 横浜でLinuxのお仕事してます

• が、今日は業務とは直接関係ない話

Page 3: LinuxのFull ticklessを試してみた

Ticklessとは• CPUが暇な(idle)時にtickを入れなくする

• 省電力

• Linux, FreeBSDなどに実装されている

timetask task

1ms tickless

idle

Page 4: LinuxのFull ticklessを試してみた

Full tickless• CPUが暇じゃなくてもtickを消す

• Linux 3.10から導入された

• tickのオーバヘッドが無くなる

timetask A task B

tickless

Page 5: LinuxのFull ticklessを試してみた

どんなワークロードのため?• Real-time • 最悪レイテンシを下げたい(極限まで)

• HPC • スループットを上げたい(極限まで)

※ただし、現在は以下の制約がある

• CPUで動作可能なタスクが1個の時だけtickを止める

• 1秒に1回はtickを入れないといけない

• CPU0はfull tickless modeにはならない

Page 6: LinuxのFull ticklessを試してみた

ビルド• Fedoraなど一般的なディストロのカーネルでは無効化されている

• git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

• menuconfigで”Full dynticks system”を有効化(CONFIG_NO_HZ_FULL=y)してコンパイル

Page 7: LinuxのFull ticklessを試してみた

実行• x86_64 2コア(CPU0, CPU1)環境で実行 • 起動パラメータに”nohz_full=1”を追加 • CPU1のみfull tickless可能に

• dmesg | grep NO_HZ • “NO_HZ: Full dynticks CPUs: 1.” ならOK • sched_clock(TSCとか)の進みが不安定な環境ではNGになる (例: VirtualBox on Mac OS X)

Page 8: LinuxのFull ticklessを試してみた

dynticks-testing(*1)

• CPU1でビジーループを10秒走らせて、その間tickがどれだけ入ったかを記録

• カーネルトレース(ftrace)の結果が出てくる

• Full ticklessのための事前セットアップもやってくれる

• 全ての外部割り込み先、RCU関連カーネルスレッドをCPU0に移動

• ただし、他タスクがCPU1に入ってこないようにする設定はやってくれない ==> Cgroup cpusetで設定

*1 git://git.kernel.org/pub/scm/linux/kernel/git/frederic/dynticks-testing.git

Page 9: LinuxのFull ticklessを試してみた

結果# TASK-PID CPU# TIMESTAMP FUNCTION # | | | | | rcuos/0-18 [001] 1233.121545: tick_stop: success=yes msg= user_loop-2412 [001] 1233.122098: tick_stop: success=no msg=more than 1 task in runqueue ! sleep-2413 [001] 1233.122419: hrtimer_expire_entry: hrtimer=ffff88042f44d900 function=tick_sched_timer now=1232550001205 sleep-2413 [001] 1233.122429: tick_stop: success=yes msg= sleep-2413 [001] 1233.122721: tick_stop: success=no msg=more than 1 task in runqueue ! sleep-2413 [001] 1233.122724: tick_stop: success=no msg=more than 1 task in runqueue ! user_loop-2412 [001] 1233.123419: hrtimer_expire_entry: hrtimer=ffff88042f44d900 function=tick_sched_timer now=1232551000974 user_loop-2412 [001] 1233.123431: tick_stop: success=yes msg= user_loop-2412 [001] 1233.123435: tick_stop: success=no msg=more than 1 task in runqueue ! user_loop-2412 [001] 1233.123436: tick_stop: success=no msg=more than 1 task in runqueue ! user_loop-2412 [001] 1233.123439: tick_stop: success=yes msg= user_loop-2412 [001] 1233.351523: hrtimer_expire_entry: hrtimer=ffff88042f44d900 function=tick_sched_timer now=1232779000584 user_loop-2412 [001] 1233.351531: tick_stop: success=no msg=more than 1 task in runqueue ! user_loop-2412 [001] 1233.351544: tick_stop: success=no msg=more than 1 task in runqueue ! kworker/1:2-2261 [001] 1233.351548: workqueue_execute_start: work struct ffff88042f44fac8: function od_dbs_timer user_loop-2412 [001] 1233.352523: hrtimer_expire_entry: hrtimer=ffff88042f44d900 function=tick_sched_timer now=1232780000291 user_loop-2412 [001] 1233.352526: tick_stop: success=yes msg= user_loop-2412 [001] 1233.435561: hrtimer_expire_entry: hrtimer=ffff88042f44d900 function=tick_sched_timer now=1232863000250 user_loop-2412 [001] 1233.435564: tick_stop: success=no msg=more than 1 task in runqueue ! 以下、500行(full tickless無効の場合10000行)くらい続く. . .

Page 10: LinuxのFull ticklessを試してみた

結果(要約)

• 明らかにtickが減っている→動作はしている

• しかし、tickless期間は平均0.1秒(10秒÷102) • 制約の1秒にはまだ遠い

Full tickless無効 Full tickless有効

タイマ発火回数(10秒間) 10019回 102回

※ HZ=1000(1秒間に1000回のtick)環境で実行

Page 11: LinuxのFull ticklessを試してみた

kworkerスレッド(workqueue)

• ビジーループ以外にCPUごとのkworkerスレッドが動いている(別のCPUに移動できない) →動作可能タスクが複数 →full tickless modeに移行しない

Full ticklessなし Full ticklessあり

タイマ発火回数(10秒間) 10019回 102回

kworker動作回数 (10秒間) 1043回 96回

Page 12: LinuxのFull ticklessを試してみた

kworkerスレッドが実行していたもの関数名 サブシステム

od_dbs_timer CPUfreq(CPU frequency scaling)

output_poll_execute [drm_kms_helper]

DRM(Direct Rendering Manager)

vmstat_update メモリ管理

blk_delay_work ブロックデバイス

ioc_release_fn ブロックデバイス

disk_events_workfn ブロックデバイス

flush_to_ldisc TTY

Page 13: LinuxのFull ticklessを試してみた

対策 - od_dbs_timer()• 実行されていた関数がdrivers/cpufreq/cpufreq_ondemand.cにあるので、周波数の動的変更が関係しているに違いない!

• # cpupower frequency-set -g performance としたら出なくなった

• CONFIG_CPU_FREQ=nでカーネル再ビルドでも良いらしい(*1)

*1 linux/Documentation/kernel-per-CPU-kthreads.txt

Page 14: LinuxのFull ticklessを試してみた

対策 - output_poll_execute()• drm_kms_helperをrmmodできれば良い# init 3# echo 0 > /sys/class/vtconsole/vtcon1/bind# rmmod radeon# rmmod drm_kms_helper

• ただし、モニタ&キーボードが使えなくなる

Page 15: LinuxのFull ticklessを試してみた

対策 - vmstat_update()• linux/Documentation/kernel-per-CPU-kthreads.txt によると、 It is not possible to entirely get rid of OS jitter from vmstat_update() on CONFIG_SMP=y systems, but you can decrease its frequency by writing a large value to /proc/sys/vm/stat_interval.

• 実はdynticks-testingでは既に頻度を下げているsysctl vm.stat_interval=120

Page 16: LinuxのFull ticklessを試してみた

対策 - それ以外

• 未対策

• インメモリ動作にしてブロックデバイスを使わないとか?

• TTY…

関数名 サブシステム

blk_delay_work ブロックデバイスioc_release_fn ブロックデバイスdisk_events_workfn ブロックデバイスflush_to_ldisc TTY

Page 17: LinuxのFull ticklessを試してみた

とりあえずリトライした結果

• tickless期間が平均0.1→0.3秒に改善

Full ticklessなし Full ticklessあり (対策なし)

Full ticklessあり(対策あり)

タイマ発火回数(10秒間) 10019回 102回 33回

kworker動作回数 (10秒間) 1043回 96回 6回

Page 18: LinuxのFull ticklessを試してみた

一応、0.8秒近く持続してる時もある

Page 19: LinuxのFull ticklessを試してみた

まとめ• カーネルビルドはかんたん

• 事前セットアップが大変

• 今後の課題 • 残りのkworker実行関数の対策(根本的にはworkqueueの改造が必要かも)

• ARMとかでも試してみたい • 性能評価