Linux

Linuxでfioを使ってディスクの性能を測る(HDD,SSD)

Linuxでfioを使ってディスク(HDD,SSD)の性能を測る方法を紹介します。

fioは以下のようなディスク関連の性能調査やチューニングに役に立ちます。

・Linuxでファイルの読み書きが遅いので調べたい。

・作成したプログラムのファイルの読み書きの性能を上げたいが、どこまで処理スレッドを増やしてI/O負荷を上げれるかを知りたい。

・I/Oのチューニングをしたい。

CentOS 7.9 で動作確認しています。

Windows OS のディスク性能は、CrystalDiskMarkが利用可能です。

CrystalDiskMark
HDD搭載PCが遅いときに CrystalDiskMarkで速度調査!パソコンが遅い感じたら、まず、ディスクの性能を見てみましょう。 CrystalDiskMarkで読み書きの速度を簡単に測定可能です...

インストール

・CentOS/RHEL
yum install fio

・Ubuntu
apt install fio

fio のオプション

主要なオプション

・filename:指定したファイルパスにテスト用のファイルを作成する
★複数のディスクがマウントされている場合があるので、測定したいディレクトリ付きでファイル名を指定する
mountコマンド、 /etc/fstab で確認。マウントしているファイルシステム

・direct:trueの場合にはnon-buffered I/Oで計測する。
★OSバッファを使いたくない場合は1を指定
1: Disk I/O性能を測るので、Linuxのキャッシュを 素通りするようにする。

・rw:I/Oのパターンを指定。
read、randread、write、randwrite
シーケンシャルread、ランダムread、シーケンシャルwrite、ランダムwrite

・bs:I/Oで利用するブロックのサイズ
★プログラムのI/Oの単位に合わせる。分からなければ、straceなどで writeのサイズを確認する

・size:I/Oで利用する合計のサイズ
★プログラムでよく使うサイズを指定する。通常100GBのファイルを扱うのに、1GBなど極端に差があるサイズを指定しない。

・numjobs:パフォーマンス計測時のプロセス/ストッドの数 ★並列実行数

・runtime:実行時間の限度。秒単位。

・group_reporting:有効にするとnumjobsで複数処理した結果をまとめて表示する

・name=ジョブの名前

■参考
・PostgreSQLのブロックサイズ(ページサイズ)は、8KBです。

・Hadoop(HDFS)のブロックサイズは、64MBや128MBが使用されます。

実行方法

以下の条件での実行例です。

・ディレクトリ:/data/fio-test/
・測定に使うファイルサイズ:10GB
・並列度:8
・I/Oで利用するブロックのサイズ:128kB

<実行コマンド例>
(いろいろ引数を変えてデータを採取したほうがいいので、コピペしてスクリプトにしたほうが効率的です。)

#ランダムread
fio -filename=/data/fio-test/testfile01 -direct=0 -rw=randread -bs=128k -size=10g -numjobs=8 -runtime=60 -group_reporting -name=TestProgram1-io-perf-randomread -output=TestProgram1-io-perf-randomread.txt

#シーケンシャルread
fio -filename=/data/fio-test/testfile02 -direct=0 -rw=read -bs=128k -size=10g -numjobs=8 -runtime=60 -group_reporting -name=TestProgram1-io-perf-sequentialread -output=TestProgram1-io-perf-sequentialread.txt

#ランダムwrite
fio -filename=/data/fio-test/testfile03 -direct=0 -rw=randwrite -bs=128k -size=10g -numjobs=8 -runtime=60 -group_reporting -name=TestProgram1-io-perf-randaom-write -output=TestProgram1-io-perf-randwrite.txt

#シーケンシャルwrite
fio -filename=/data/fio-test/testfile04 -direct=0 -rw=write -bs=128k -size=10g -numjobs=8 -runtime=60 -group_reporting -name=TestProgram1-io-perf-sequentialwrite –output=TestProgram1-io-perf-sequentialwrite.txt

TIPS

プログラムで並列度を指定できるものは、並列度(numjobs)を変えて測定し、そのディスクに最適な値を探すといいですね。

並列度が低すぎるとディスクの性能を引き出せません。
逆に高すぎても、I/O待ちが発生してベストな性能は出せません。

性能が安定しない時は、-runtime の値を長くすると安定することがあります。

fio の出力の見方

いろいろ情報が出力されますが、
とりあえず、「IOPS」と「BW」(スループット)の行を見ればいいです。

read: IOPS=42.0k, BW=671MiB/s (704MB/s)(400MiB/596msec)

$
$
$ fio -filename=testfile01 -direct=0 -rw=randread -bs=16k -size=100m -numjobs=4   -group_reporting -name=TestProgram1-io-perf-randomread  -output=TestProgram1-io-perf-randomread.txt

$ cat TestProgram1-io-perf-randomread.txt
TestProgram1-io-perf-randomread: (g=0): rw=randread, bs=(R) 16.0KiB-16.0KiB, (W) 16.0KiB-16.0KiB, (T) 16.0KiB-16.0KiB, ioengine=psync, iodepth=1
...
fio-3.7
Starting 4 processes

TestProgram1-io-perf-randomread: (groupid=0, jobs=4): err= 0: pid=5537: Wed Feb 23 21:13:13 2022
   read: IOPS=42.0k, BW=671MiB/s (704MB/s)(400MiB/596msec)
    clat (nsec): min=1107, max=9776.9k, avg=87448.92, stdev=295765.43
     lat (nsec): min=1128, max=9776.0k, avg=87517.06, stdev=295784.46
    clat percentiles (nsec):
     |  1.00th=[   1432],  5.00th=[   1672], 10.00th=[   1752],
     | 20.00th=[   1880], 30.00th=[   1960], 40.00th=[   2064],
     | 50.00th=[   2256], 60.00th=[   2576], 70.00th=[   3760],
     | 80.00th=[ 234496], 90.00th=[ 301056], 95.00th=[ 354304],
     | 99.00th=[ 518144], 99.50th=[ 618496], 99.90th=[6193152],
     | 99.95th=[7176192], 99.99th=[9502720]
   bw (  KiB/s): min=90016, max=111648, per=14.75%, avg=101358.50, stdev=9201.30, samples=4
   iops        : min= 5626, max= 6978, avg=6334.75, stdev=575.14, samples=4
  lat (usec)   : 2=33.54%, 4=37.73%, 10=2.42%, 20=0.09%, 50=0.97%
  lat (usec)   : 100=0.18%, 250=7.89%, 500=16.07%, 750=0.77%, 1000=0.10%
  lat (msec)   : 2=0.08%, 4=0.02%, 10=0.13%
  cpu          : usr=0.99%, sys=11.52%, ctx=6419, majf=0, minf=159
  :

以下のようにファイルに出力し、IOPSで grepすればデータの集計が簡単です。

$
$
$ grep IOPS *.txt
TestProgram1-io-perf-randomread.txt:   read: IOPS=57.0k, BW=445MiB/s (467MB/s)(400MiB/898msec)

TestProgram1-io-perf-randwrite.txt:  write: IOPS=351k, BW=2740MiB/s (2873MB/s)(400MiB/146msec)

TestProgram1-io-perf-sequentialread.txt:   read: IOPS=351k, BW=2740MiB/s (2873MB/s)(400MiB/146msec)

TestProgram1-io-perf-sequentialwrite.txt:  write: IOPS=308k, BW=2410MiB/s (2527MB/s)(400MiB/166msec)

ディスク(ストレージ)の性能とは

一般的に 以下の3つの指標でディスクのパフォーマンスとします。

・IOPS
・レスポンスタイムもしくはレイテンシ
・スループット

1.IOPS(Input Output Per Second)
:秒間のI/O数
:IOPS=アームの動く時間+回転待ち時間+実際の読み書き時間
:I/Oのサイズが大きくなるとIOPSが減る
:ランダムI/Oの性能を見る場合にはこの値を見ると良い

2.レスポンスタイム(応答時間)もしくはレイテンシ
:I/O要求をストレージシステムが受けてから応答が返ってくるまでの時間
:個々のI/O要求へのレスポンスタイムである点が大切。レスポンスタイムが多少遅くても並行して処理を行うことができれば全体の仕事量は増やすことができる

3.スループット
:時間当たりの仕事量

複数のHDDでRAIDを組んたときの性能

ディスク回転数7200rpm、データ転送速度 200MiB/s の HDDを10数個でRAIDを組んだ時の性能です。

ディスクの本数やディスクコントローラーの性能、RAIDコントローラーのディスクキャッシュメモリの大きさや、

ライトバックキャッシュメモリを持っているかなどで大きく変わるので、
ハードウェアの仕様を確認して検証してくださいね。

■一般的にも以下のような傾向になります。どこで頭打ちになるかの違いです。

・並列度を上げるとIOPS、BW(スループット)ともに向上。
(当然、物理的な限界はあります。ディスクの本数やディスクコントローラーの性能に依存)

・IOサイズが変わってもBW(スループット)はほぼ同じ。
全体の処理量は変わらない。

・write(書き込み)は、readに比べ、並列度を上げても処理量が増えない。

ディスクの性能測定は、ディスクコントローラーもキャッシュするし、OSもキャッシュするので、なかなか難しいです。

正確に実施するには、OSコマンドでキャッシュを飛ばす(クリア)したり、工夫が必要です。

あとがき

何かディスクのI/Oが遅そうなときは、fioでデータを採取したほうがいいですね。

ディスクが遅くてI/Oが多いから、MySQLデータベースの限界性能です。と言えたりします。

その時は、対象のソフトウェアが読み書きするブロックサイズで測定しましょう。

また、straceを組み合わせるとより詳細に分析可能です。(writeの実行数や、書き込み数など)

Linux straceコマンドでシステムコールをトレースしデバッグする。プログラムの動作確認、性能調査に役に立つLinuxのstraceコマンドを使いこなせると、プログラムのデバッグや性能問題など調査に非常に役に立ちます。 この記事では実用的...
Azure ディスク性能調査。たまに遅くなり安定しないAzure上で、Linux(CentOS/Ubuntu)を動かしていますが、ディスク性能が安定しません。 たまに非常に遅くなります...