LeavaTailの日記

LeavaTailの日記

Linuxエンジニアを目指した技術者の備忘録

I/O スケジューラの違いによるストレージの書き込み性能を比較する

注意

本記事は、特定の環境下における特定の書き込みパターンを測定した結果であり、 I/O スケジューラの優劣を決めるものではない。

関連記事

leavatail.hatenablog.com

概要

本記事では、I/Oスケジューラの違いによって、次のようなストレージへの書き込み特性について確認した。

今回の環境(Raspberry Pi 4 と SSD/SDカード) と測定方法では、それぞれのI/Oスケジューラ (パラメータはデフォルト値) による大きな違いは見られなかった。

はじめに

汎用的なストレージデバイスは、その特性からまとまったデータ量のI/Oであるほうが効率が良いとされている。
しかし実際には、アプリケーションがそういったI/Oが発行されるとは限らない。

Linuxカーネルには、I/Oスケジューラと呼ばれるI/Oリクエストの処理順番を入れ替えたり、まとめたりすることで応答速度やスループットを向上を目的とした機能である。
I/Oスケジューラにはそれぞれ異なる特性があり、システム環境やストレージデバイスなどによって、I/O性能が変わってくる。

ここでは、OSの機能の一機能 "I/Oスケジューラ"に注目して、それぞれの書き込みの違いを確認する。

Linux Kernel v5.15 では、mq-deadlinebfq (Budget Fair Queuing)、kyber がサポートしている。

mq-deadline の概要

mq-deadlineは、デッドラインを設けることでリクエストの処理開始時間を保障する I/Oスケジューラの一つである。

Linux Kernel v5.15 のデフォルト値では、書き込みリクエストの有効期限は 5秒 、読み込みリクエストの有効期限は 500 ミリ秒 となる。

bfq の概要

bfq は、単一のアプリケーションがすべての帯域幅を使用しないようスケジュールする I/Oスケジューラの一つである。

Linux Kernel 5.15 のデフォルト値では、スループットの最大化よりもレイテンシの最小化を達成することを目的とする。
そのため、低速のCPUに対して高速なストレージデバイスに対しては、bfq I/Oスケジューラは不向きとなることがある。

kyber の概要

mq-deadlineは、ブロックレイヤに渡されたI/O要求のレイテンシを計算し、目標とするレイテンシを達成するような I/Oスケジューラの一つである。

Linux Kernel v5.15 のデフォルト値では、目標とする読み込みレイテンシは 2ミリ秒 、同期書き込みのレイテンシは 10 ミリ秒 となる。

目的

I/Oスケジューラの違いによって、次のような書き込み特性がどのように変化するかを調査する。

実行環境

Raspberry Pi 4 Model B (Raspberry Pi 4) は microSDカード経由でRaspberry Pi OSを起動させる。 また、Raspbery Pi 4 の USB3.0ポートにポータブルSSDを接続する。

計測環境の概要

ここで使用する実験環境について下記に示す。

項目 概要
Board Raspberry Pi 4
CPU Cortex-A72 (ARM v8) 1.5GHz
メモリ 4GB LPDDR4-3200
OS Raspberry Pi OS (64 bit) (Feb 21st 2023)
kernel v5.15.92
ファイルシステム ext4
BCC Utilities bpfcc-tools version 0.18.0+ds-2
ext4 Utilities E2fsprogs version 1.46.2
fio fio-3.25-2
OS格納先ストレージ microSDHC 16GB Class10 UHS-1
計測用ストレージ(外付けSSD) SL-MG5
計測用ストレージ(SDカード) SF-E64

この実験では、 外付け SSD/SDカードに対する書き込みを計測する。

計測方法

ストレージへの書き込みをする負荷プログラムとして fio を実行し、次のような情報を取得することでI/Oスケジューラの比較する

毎計測時、デフォルトパラメータでmkfsコマンドの実行と、 echo 3 > /proc/sys/vm/drop_cachesによるキャッシュ解放を実施する。
biosnoopmpstatによる計測は、ファイルシステムをマウント(mount)してからアンマウント(umount)までとする。

その区間に負荷プログラム(fio)を実行し、そのときのIO要求のデータを使用する。

計測の流れを図にすると下記のようになる。

計測のタイムライン

ここで、白色の丸は "非同期処理"であり、黒色の丸は "同期処理" を表している。

また、各実験は3回ずつ施行する。

スループットの計測

fioでは、合計 32GB となるような 次の4パターンを2つのアクセス手法 (sequential/random) のジョブとして実行する。

write
パターン1
write
パターン2
write
パターン3
write
パターン4
bs 1M 1M 1M 1M
size 32G 8G 8G 8G
numjobs 1 4 1 4
iodepth 1 1 4 4

この実験では、異なる計測用ストレージとI/Oスケジューラに対して、これらを実行する。

BIO毎のレイテンシ計測

BPF Compiler Collection (BCC) を利用することで、ユーザプログラムから IO要求発行に任意の処理を追加し、IO要求の内容を確認する。

今回の計測では、BCCのサンプルスクリプトとして提供されている biosnoop を利用する

biosnoop は、IO要求発行(blk_mq_start_request)と IO完了(blk_account_io_done) における BIO のステータスを確認することができる。
このスクリプトを実行することで下記のような結果を得ることができる。

TIME(s)     COMM           PID    DISK    T SECTOR     BYTES  QUE(ms) LAT(ms)
0.000000    mount          4349   sda     R 2050       1024      0.06    0.46
0.000396    mount          4349   sda     R 2048       4096      0.05    0.19
0.000713    mount          4349   sda     R 2056       4096      0.05    0.18
0.000826    mount          4349   sda     R 2064       4096      0.05    0.18
0.000968    mount          4349   sda     R 2072       4096      0.05    0.16
0.001165    mount          4349   sda     R 2080       4096      0.09    0.17

ここから書き込み先デバイス (DISK) と アクセス方向 (T) でフィルターをかける。
ここから、タイムスタンプ (TIME), オフセット (SECTOR)とサイズ (SIZE)を抽出する。

CPU使用率の計測

mpstatを利用することで、次のようなプロセッサ関連の統計情報を表示することができる。

Linux 5.15.92-v8 (raspberrypi)  09/09/2023      _aarch64_       (4 CPU)

10:59:25 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
10:59:26 PM  all    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
10:59:27 PM  all    0.00    0.00    0.25    0.00    0.00    0.00    0.00    0.00    0.00   99.75
10:59:28 PM  all    0.25    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   99.75
10:59:29 PM  all    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
10:59:30 PM  all    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

今回は、CPU使用率を確認するために mpstat をバックグラウンドで実行する。

準備

Linuxカーネルの再構築

BCCは、特定のカーネルコンフィグに依存しているが、Raspberry pi OS のデフォルトで無効となっている。

そこで、公式手順に基に、独自にカーネルのビルド・インストールを実施する。
カーネルコンフィグは、デフォルトのカーネルコンフィグから次のように修正する。

user@hostname:~/linux$ ./scripts/diffconfig .config.old .config
IKHEADERS n -> y

また、Kyber と BFQ はデフォルトで無効となっているため、カーネルコンフィグを更新しておく。

user@hostname:~/linux$ ./scripts/diffconfig .config.old .config
MQ_IOSCHED_KYBER=y
IOSCHED_BFQ=y

必要なパッケージのインストール

今回の計測するにあたって、Raspberry Pi OS にプリインストールされているパッケージのみでは不足している。

そこで、計測用にdebianパッケージを追加でインストールする。

pi@raspberrypi:~$ sudo apt install bpfcc-tools

BPFスクリプトの修正

debian (bullseye) が提供する bpfcc-toolsパッケージは、upstreamより古いバージョンとなっている。

今回使用しているバージョンには、BYTESの値で不適切となる不具合があったため、次のコミットをcherry-pickした。

github.com

また、今回の計測では短時間に多くのBIO情報が出力されるため、リングバッファ (page_cnt) のサイズも拡張しておく。

実験結果

スループット

I/Oスケジューラの違いによるパフォーマンスを比較する。 パフォーマンス測定には fio の実行結果からbwを抽出した。

外付けSSDに対する書き込みスループット

(Raspberry Pi 4と比較して) 高速なSSDの場合には、bfq I/Oスケジューラが他と比較してスループットが低めとなっているように見える。
特に、numjobs=1, iodepth=4 のシーケンシャルな書き込みでは、mq-deadline I/Oスケジューラと比較しても 5%程の低下がみられた。

これは、bfq I/Oスケジューラのデフォルト値における特性では、"低速のCPUに対して高速なストレージデバイスに対しては、bfq I/Oスケジューラは不向きとなることがある" ことが関係しているのかもしれない。

SDカードに対するランダムな書き込みスループット

一方で、SDカードの場合には、mq-deadline I/Oスケジューラが他と比較してスループットが低めとなっているように見える。

mq-deadline I/Oスケジューラのスループットが none と同様であることを考えると、mq-deadlineによるスケジューリングが有効に動作していないと見える。
そのため、書き込みの有効期限などスケジューラのパラメータをチューニングすることで、パフォーマンスは変わるかもしれない。

レイテンシ

I/Oスケジューラの違いによるレイテンシ(IO要求発行時から完了までの時間) を比較する。

ここでは、最も複雑なパターン4 (numjobs=4, iodepth=4) の結果のみ注目する。

各I/Oスケジューラにおいて、biosnoop で得られたレイテンシでヒストグラムでプロットした。 (左から I/Oスケジューラが"mq-deadlie", "kyber", "bfq", "none"の順で表示)

これらのグラフは、横軸がレイテンシ縦軸が発生頻度を表しているため、左上にプロットが集中しているほど平均レイテンシが小さいことを意味する。

外付けSSDに対する書き込みによるレイテンシ

外付けSSDに対するランダムな書き込みによるレイテンシ

外付けSSDに対するシーケンシャルな書き込みによるレイテンシには、次のような傾向が見られた。

  • mq-deadline と kyberの I/Oスケジューラは、bfq I/Oスケジューラと比較して、低レイテンシの頻度は少ないが、高レイテンシの頻度も少ない
  • mq-deadline と kyberの I/Oスケジューラは、bfq I/Oスケジューラと比較して、高レイテンシの頻度も少ない

一方で、ランダムな書き込みによるレイテンシには、次のような傾向が見られた。

  • mq-deadline I/Oスケジューラは、kyber と bfq I/Oスケジューラと比較して、結果のばらつきが小さい
  • ただし、それぞれの I/Oスケジューラでのレイテンシの違いに大きな差分はない

SDカードに対する書き込みによるレイテンシ

SDカードに対するランダムな書き込みによるレイテンシ

SDカードに対する書き込みによるレイテンシについては、それぞれの I/Oスケジューラでのレイテンシの違いに大きな差分はなかった

CPU使用率

I/Oスケジューラの違いによるCPU使用率(すべてのコアの合算値)を比較する。

レイテンシと同様に、最も複雑なパターン4 (numjobs=4, iodepth=4) の結果のみ注目する。

各I/Oスケジューラにおいて、mpstat で得られたCPU利用状況を内訳によって積み上げグラフとしてプロットした。 (左から I/Oスケジューラが"mq-deadlie", "kyber", "bfq", "none"の順で表示)

これらのグラフは、赤色がカーネルで実行されたCPU利用の割合を表しているため、赤色の割合が大きいほどI/Oスケジューラによるオーバーヘッドが大きいことを意味する。

外付けSSDに対する書き込みによるCPU使用率

外付けSSDに対するランダムな書き込みによるCPU使用率

SDカードに対する書き込みによるCPU使用率

SDカードに対するランダムな書き込みによるCPU使用率

CPU使用率の観点では、それぞれのケースにおいてI/Oスケジューラによるオーバーヘッド (赤色がグラフを占める割合) に大きな差分はなかった

ただし、mq-deadline I/Oスケジューラでは、 カーネルで実行されたCPU利用にばらつきが大きい。

おわりに

本記事では、ファイルシステムの違いによるストレージへの書き込みについて以下の3点に着目して計測した。

今回はI/Oスケジューラのパラメータをチューニングしていないため、参考値ではあるが I/Oスケジューラによる大きな違いは見られなかった。
また、この実験は利用的な環境 (ユーザからこのプロセスしか動かしておらず、負荷が大きいプロセスもこのプロセスのみである) であるため、実際には結果が大きく異なることが予想される。

そのため、それぞれのユースケースに沿って環境を選定することが必要となってくる

変更履歴

  • 2023/10/01: 記事公開
  • 2023/11/19: 関連記事を追加

参考