本記事は、特定の環境下における特定の書き込みパターンを測定した結果であり、ファイルシステムの優劣を決めるものではない。
概要
本記事では、eBPF と fio を用いて、次のようなストレージへの書き込み特性について確認した。
- IO要求の発行回数
- 書き込み総量
- 書き込み頻度とオフセット
Linuxファイルシステム (ext4, xfs, nilfs2, f2fs, exfat, btrfs, jfs) 毎にどのような特性があるかをまとめた。
はじめに
フラッシュメモリは、ハードディスクといったストレージデバイスと比較して、アクセス速度や省電力が優れている。 そのため近年、SDメモリカードやSSDといったフラッシュメモリを搭載したストレージデバイスが広く普及している。
一方で、フラッシュメモリはその仕組みにより、ハードディスクと比較して「データ書き込み回数」に限りがあるといった課題がある。
ストレージデバイス搭載コントローラが直寿命化するような工夫が施されていたりするが、アプリケーション側でも工夫することでその効果はさらに高めることができる。
ここでは、OSの機能の一機能 "ファイルシステム"に注目して、それぞれの書き込みの違いを確認する。
目的
ファイルシステムの違いによって、次のような書き込み特性がどのように変化するかを調査する。
- IO要求の発行回数
- 書き込み総量
- 書き込み頻度とオフセット
実行環境
Raspberry Pi 4 Model B (Raspberry Pi 4) は microSDカード経由でRaspberry Pi OSを起動させる。 また、Raspbery Pi 4 の USB3.0ポートにポータブルSSDを接続する。
ここで使用するRaspberry Pi 4のスペックについて、必要な情報だけ抜粋したものを下記に示す。
項目 | 概要 |
---|---|
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 |
I/O Scheduler | mq-deadline |
BCC Utilities | bpfcc-tools version 0.18.0+ds-2 |
ext4 Utilities | E2fsprogs version 1.46.2 |
xfs Utilities | xfsprogs version 5.10.0-4 |
nilfs2 Utilities | nilfs-tools version 2.2.8-1 |
f2fs Utilities | f2fs-tools version 1.14.0-2 |
exfat Utilities | exfatprogs version : 1.1.0-1 |
btrfs Utilities | btrfs-progs version 5.10.1-2 |
jfs Utilities | jfsutils version 1.1.15-5 |
fio | fio-3.25-2 |
OS格納先ストレージ | microSDHC 16GB Class10 UHS-1 |
計測用ストレージ | SL-MG5 |
この実験では、 ポータブル SSD (SL-MG5) に対する書き込みを計測する。
計測方法
BPF Compiler Collection (BCC) を利用することで、ユーザプログラムから IO要求発行に任意の処理を追加し、IO要求の内容を確認する。
今回の計測では、BCCのサンプルスクリプトとして提供されている biosnoop を利用する。
biosnoop は、IO要求発行(blk_mq_start_request
)と IO完了(blk_account_io_done
) における BIO のステータスを確認することができる。
このスクリプトを実行することで得られる書き込み先デバイス (DISK
) と アクセス方向 (T
) でフィルターをかける。
ここから、タイムスタンプ (TIME
), オフセット (SECTOR
)とサイズ (SIZE
)を抽出する。
また、ストレージへの書き込みをする負荷プログラムとして fio を実行する。
fioでは、合計 32GB となるように 以下の2パターンからデータを書き込みをする。
並列度1 でシーケンシャルな書き込みをする
fio -directory=/mnt/fio-test -direct=0 -rw=write -bs=256k -size=32G -numjob=1 -invalidate=1 -fsync_on_close=1 -group_reporting
並列度8 でランダムな書き込みをする
fio -directory=/mnt/fio-test -direct=0 -rw=randwrite -bs=256k -size=4G -numjob=8 -invalidate=1 -randseed=1 -fsync_on_close=1 -group_reporting
この実験では、これらのツールを活用して異なるファイルシステムに実行する。
毎計測時、デフォルトパラメータでmkfs
コマンドの実行と、 echo 3 > /proc/sys/vm/drop_caches
によるキャッシュ解放を実施する。
biosnoop
による計測は、ファイルシステムをマウント(mount
)してからアンマウント(umount
)までとする。
その区間に負荷プログラム(fio
)を実行し、そのときのIO要求のデータを使用する。
準備
Linuxカーネルの再構築
BCCは、特定のカーネルコンフィグに依存しているが、Raspberry pi OS のデフォルトで無効となっている。
そこで、公式手順に基に、独自にカーネルのビルド・インストールを実施する。
カーネルコンフィグは、デフォルトのカーネルコンフィグから次のように修正する。
user@hostname:~/linux$ ./scripts/diffconfig .config.old .config
IKHEADERS n -> y
必要なパッケージのインストール
今回の計測するにあたって、Raspberry Pi OS にプリインストールされているパッケージのみでは不足している。
そこで、計測用にdebianパッケージを追加でインストールする。
pi@raspberrypi:~$ sudo apt install bpfcc-tools
pi@raspberrypi:~$ sudo apt install nilfs-tools exfatprogs xfsprogs jfsutils reiserfsprogs f2fs-tools btrfs-progs
BPFスクリプトの修正
debian (bullseye) が提供する bpfcc-toolsパッケージは、upstreamより古いバージョンとなっている。
今回使用しているバージョンには、BYTES
の値で不適切となる不具合があったため、次のコミットをcherry-pickした。
また、今回の計測では短時間に多くのBIO情報が出力されるため、リングバッファ (page_cnt
) のサイズも拡張しておく。
実験結果
IO要求の発行回数
biosnoop
によって得られた結果から BYTES
を抽出し、IO要求の発行回数をサイズごとに抽出した。
シーケンシャルな書き込み (並列度1) の場合は、次のような結果となった。
この場合、それぞれのファイルシステムで大きな差は見られなかった。
また、それぞれのファイルシステムでは、fioによる書き込みサイズ 256K より大きいサイズで発行されていることも分かった。
一方で、ランダムな書き込み (並列度8) の場合は、次のような結果となった。
この場合、先ほどのシーケンシャルな書き込みと比較していくつかの特徴がみられた。
- f2fs と nilfs2 ファイルシステムは、シーケンシャルな書き込み(並列度1) とランダムな書き込み (並列度8) で似た傾向となった
- ext4、xfs と btrfs ファイルシステムは、ランダムな書き込み (並列度8) では アプリケーションからの書き込みサイズ(256K) のIOが増えたため、IO総数も増えた
- exfat と jfs ファイルシステムは、ランダムな書き込み (並列度8) では小さいIOに分割されて発行されたため、IO総数が増大した。
メタデータ書き込み総量
biosnoop
によって得られた結果から BYTES
を抽出し、その合計値を計算することでストレージへの書き込み総量を計算する。
さらに、ファイルの実データ (32GB) を減算することで、メタデータの書き込み総量を算出した。
- Pattern 1: シーケンシャルな書き込み (並列度1)
- Pattern 2: ランダムな書き込み (並列度8)
上記2パターンで計測したときのメタデータの書き込み総量は、次のようになった。 (単位は MB)
ext4 | xfs | nilfs2 | f2fs | exfat | btrfs | jfs | |
---|---|---|---|---|---|---|---|
1 | 70.54 | 2.11 | 572.77 | 130.05 | 0.21 | 56.00 | 488.95 |
2 | 440.60 | 4.88 | 2296.04 | 414.20 | 32743.73 | 376.04 | 1148.64 |
ここから、メタデータによる書き込み総量の増加率を計算した結果、次のようになった。
ext4 | xfs | nilfs2 | f2fs | exfat | btrfs | jfs | |
---|---|---|---|---|---|---|---|
1 | +0.22% | +0.01% | +1.75% | +0.40% | +0.00% | +0.17% | +1.49% |
2 | +1.34% | +0.01% | +7.01% | +1.26% | +99.93% | +1.15% | +3.51% |
この結果から、次のような特徴がみられた。
- exfatを除いたファイルシステムは、並列度1から8にしたときにメタデータ書き込み総量は増加している。
- 書き込み先ファイルが 1 から 8 に増えたため、メタデータの総量が増えるのは妥当であると思える。
- exfatファイルシステムは、並列度1 ではメタデータ書き込み総量が最も少なかったが、並列度8になると膨大となった。
書き込み頻度とオフセット
biosnoop
によって得られた結果からTIME
,SECTOR
,BYTES
を抽出することで、「いつ」「どこに」書き込みを実施したかを図示する。
シーケンシャルな書き込み(並列度1)を青色、ランダムな書き込み (並列度8) を水色で同時に図示している。
ext4ファイルシステムは、次のようなストレージアクセスが見られた。
シーケンシャルな書き込み (並列度1)の場合、ジャーナルファイルとターゲットファイルの2つの直線が見られる。
その一方で、ランダムな書き込み(並列度8)の場合、書き込みが分散されているように見える。
xfsファイルシステムは、同じジャーナリングファイルシステムであるext4と傾向は似ている。
nilfs2ファイルシステムは、ログ構造化ファイルシステムであるため、どちらのパターンにおいても直線となっている。
f2fsファイルシステムも、ログ構造化ファイルシステムであるため、nilfs2と傾向は似ている。
exfatファイルシステムは、一定のところまで書いた後に断片化した書き込みが長時間続いている。
btrfsファイルシステムでは、並列度に応じて書き込みが分散しているように見える。
jfsファイルシステムでは、ストレージデバイス全体を一定間隔に書き込みをしている。
パフォーマンス
今回の実験では、Trim命令を明示的に発行していない。また、測定用にバックグラウンドプロセスがいくつか動いている。そのため、これらの値は参考値として算出した。
fio
によって得られた結果にあるbw
を抽出した。
- Pattern 1: シーケンシャルな書き込み (並列度1)
- Pattern 2: ランダムな書き込み (並列度8)
上記2パターンで計測したときの書き込み性能は、次のようになった。
ここでは、 f2fs と exfat ファイルシステムの特性について特筆する。
- f2fs ファイルシステムは、並列かつランダムな書き込みであっても一定のパフォーマンスを出すことができる。
- exfat ファイルシステムでは、並列かつランダムな書き込みが苦手であり、シーケンシャルな書き込みに比べて 20% ほどしかパフォーマンスが出ていない。
おわりに
本記事では、ファイルシステムの違いによるストレージへの書き込みについて以下の3点に着目して計測した。
- IO要求の発行回数
- メタデータ書き込み総量
- 書き込み頻度とオフセット
計測の結果、アプリケーションの書き込みパターンがこれらに大きく影響するような結果となった。
また、今回は対象外としたが、ファイルシステムによってはデータ完全性を保障したり、ユーザビリティを向上させるような機能がある。
さらに、今回はデフォルトのパラメータで計測したが、ファイルシステムによってはmkfsのオプションやmountのオプションでデバイスに最適化した書き込みができるようになる。
そのため、今回のデータのみではファイルシステムの優劣をつけることはできず、それぞれのユースケースに沿ってファイルシステムを選定することが必要となってくる。
変更履歴
- 2023/3/22: 記事公開