はじめに
システムのパフォーマンス問題を調査する際、ディスクI/Oのレイテンシは重要な指標の一つである。
特に、データベースやファイルサーバーなど、ディスクアクセスが頻繁に発生するアプリケーションでは、I/Oレイテンシがボトルネックになることが多い。
今回は、iopingというツールを使ってディスクI/Oのレイテンシを測定してみる。iopingはpingコマンドのディスク版のようなツールで、シンプルで直感的にI/Oレイテンシを測定できる。
環境
Ubuntu 24.04.2 LTS
ioping 1.3iopingとは
iopingは、ディスクI/Oのレイテンシを測定するためのツール。pingコマンドがネットワークのレイテンシを測定するように、iopingはディスクアクセスのレイテンシを測定する。
測定できる指標について
| 指標 | 説明 |
|---|---|
| レイテンシ | 1回のI/O操作にかかる時間 |
| IOPS | 1秒間に実行できるI/O操作数 |
| スループット | 1秒間に転送できるデータ量 |
iopingのインストール
sudo apt update
sudo apt install iopingログ
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages were automatically installed and are no longer required:
crack-common gyp libcares2 libdouble-conversion3 libgl1-amber-dri libglapi-mesa libjs-async libjs-events
libjs-inherits libjs-is-typedarray libjs-prettify libjs-regenerate libjs-source-map libjs-sprintf-js
libjs-typedarray-to-buffer libllvm17t64 liblttng-ust-common1t64 liblttng-ust-ctl5t64 liblttng-ust1t64
libmd4c0 libnotify-bin libpcre2-16-0 libqt5core5t64 libqt5dbus5t64 libqt5gui5t64 libqt5network5t64
libqt5qml5 libqt5qmlmodels5 libqt5quick5 libqt5svg5 libqt5waylandclient5 libqt5waylandcompositor5
libqt5widgets5t64 libqt5x11extras5 libre2-10 libssl-dev libuv1-dev libxcb-damage0 libxcb-xinerama0
libxcb-xinput0 mesa-utils-bin node-abbrev node-ampproject-remapping node-ansi-regex node-ansi-styles
node-aproba node-are-we-there-yet node-arrify node-async node-async-each node-auto-bind
node-babel-plugin-add-module-exports node-babel7-runtime node-balanced-match node-base64-js
node-binary-extensions node-brace-expansion node-busboy node-camelcase node-caniuse-lite node-chownr
node-chrome-trace-event node-ci-info node-cjs-module-lexer node-cli-boxes node-cli-cursor node-clone
node-collection-visit node-color-convert node-color-name node-colors node-commander node-commondir
node-concat-stream node-console-control-strings node-convert-source-map node-core-js node-core-js-pure
node-core-util-is node-data-uri-to-buffer node-decompress-response node-deep-is node-defaults
node-define-property node-delegates node-depd node-diff node-electron-to-chromium node-encoding
node-end-of-stream node-err-code node-error-ex node-es-module-lexer node-escape-string-regexp
node-eslint-utils node-eslint-visitor-keys node-esquery node-estraverse node-esutils node-events
node-fancy-log node-fast-deep-equal node-fast-levenshtein node-fetch node-find-up node-flatted
node-foreground-child node-fs-readdir-recursive node-fs-write-stream-atomic node-fs.realpath
node-function-bind node-get-caller-file node-get-stream node-get-value node-glob node-globals node-got
node-graceful-fs node-growl node-has-flag node-has-unicode node-has-value node-has-values
node-hosted-git-info node-iconv-lite node-ieee754 node-iferr node-imurmurhash node-indent-string
node-inflight node-inherits node-ini node-interpret node-ip node-ip-regex node-is-arrayish
node-is-binary-path node-is-buffer node-is-descriptor node-is-extglob node-is-path-cwd node-is-plain-obj
node-is-plain-object node-is-stream node-is-typedarray node-is-windows node-isarray node-isexe
node-isobject node-js-tokens node-json-buffer node-json-parse-better-errors node-json-schema
node-json-schema-traverse node-json-stable-stringify node-jsonify node-jsonparse node-kind-of node-levn
node-loader-runner node-locate-path node-lodash-packages node-lowercase-keys node-lru-cache
node-map-visit node-memfs node-merge-stream node-mimic-response node-minimatch node-minimist
node-minipass node-mute-stream node-n3 node-negotiator node-npm-run-path node-object-inspect
node-object-visit node-once node-optimist node-optionator node-osenv node-p-cancelable node-p-limit
node-p-locate node-p-map node-pascalcase node-path-dirname node-path-exists node-path-is-absolute
node-path-is-inside node-path-type node-pify node-pkg-dir node-postcss-value-parser node-prelude-ls
node-process-nextick-args node-promise-inflight node-promise-retry node-promzard node-prr node-pump
node-punycode node-quick-lru node-randombytes node-read node-readable-stream node-rechoir
node-regenerator-runtime node-regenerator-transform node-regexpp node-regjsgen node-repeat-string
node-require-directory node-require-from-string node-resolve node-resolve-cwd node-resolve-from
node-restore-cursor node-resumer node-retry node-run-queue node-safe-buffer node-serialize-javascript
node-set-blocking node-set-immediate-shim node-shebang-command node-shebang-regex node-shell-quote
node-signal-exit node-slash node-slice-ansi node-source-list-map node-source-map node-spdx-correct
node-spdx-exceptions node-spdx-expression-parse node-spdx-license-ids node-sprintf-js node-ssri
node-stack-utils node-string-decoder node-strip-bom node-supports-color node-tapable node-terser
node-text-table node-through node-time-stamp node-to-fast-properties node-tslib node-type-check
node-typedarray node-typedarray-to-buffer node-undici node-unicode-canonical-property-names-ecmascript
node-unicode-match-property-value-ecmascript node-unicode-property-aliases-ecmascript node-unset-value
node-uri-js node-util-deprecate node-uuid node-v8flags node-validate-npm-package-license node-wcwidth.js
node-webpack-sources node-wordwrap node-wrappy node-write-file-atomic node-xtend node-y18n node-yallist
node-yaml nodejs-doc qt5-gtk-platformtheme qttranslations5-l10n qtwayland5 xbitmaps
Use 'sudo apt autoremove' to remove them.
The following NEW packages will be installed:
ioping
0 upgraded, 1 newly installed, 0 to remove and 78 not upgraded.
Need to get 18.2 kB of archives.
After this operation, 54.3 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu noble/universe amd64 ioping amd64 1.3-1 [18.2 kB]
Fetched 18.2 kB in 1s (31.1 kB/s)
Selecting previously unselected package ioping.
(Reading database ... 114617 files and directories currently installed.)
Preparing to unpack .../ioping_1.3-1_amd64.deb ...
Unpacking ioping (1.3-1) ...
Setting up ioping (1.3-1) ...
Processing triggers for man-db (2.12.0-4build2) ...インストール確認
# バージョン確認
ioping --version
# ヘルプ表示
ioping --help主要オプション一覧
I/O動作オプション
| オプション | 説明 |
|---|---|
-A, --async | 非同期I/Oを使用 |
-C, --cached | キャッシュI/Oを使用(フラッシュなし) |
-D, --direct | ダイレクトI/O使用(O_DIRECT) |
-G, --read-write | 読み書きピンポンモード |
-L, --linear | シーケンシャル操作を使用 |
-N, --nowait | nowait I/O使用(RWF_NOWAIT) |
-H, --hipri | 高優先度I/O使用(RWF_HIPRI) |
-W, --write | 書き込みI/Oを使用 |
-Y, --sync | 同期I/O使用(O_SYNC) |
-y, --dsync | データ同期I/O使用(O_DSYNC) |
-R, --rapid | 3秒間の高速I/Oテスト(-q -i 0 -w 3) |
-k, --keep | 一時ファイル保持・再利用 |
パラメータオプション
| オプション | 説明 |
|---|---|
-a, --warmup <count> | 最初の<count>回のリクエストを無視 |
-b, --burst <count> | 遅延なしで<count>回のリクエスト実行 |
-c, --count <count> | <count>回のリクエスト後に停止 |
-e, --entropy <seed> | 乱数生成器のシード値 |
-i, --interval <time> | リクエスト間隔(デフォルト1s) |
-s, --size <size> | リクエストサイズ(デフォルト4k) |
-S, --work-size <size> | 作業セットサイズ(デフォルト1m) |
-o, --work-offset <size> | 作業セットオフセット(デフォルト0) |
-w, --work-time <time> | 指定時間経過後に停止 |
-l, --speed-limit <size> | 1秒あたりの速度制限 |
-r, --rate-limit <count> | 1秒あたりのレート制限 |
-t, --min-time <time> | 最小有効リクエスト時間 |
-T, --max-time <time> | 最大有効リクエスト時間 |
出力オプション
| オプション | 説明 |
|---|---|
-B, --batch | 最終統計を生フォーマットで出力 |
-I, --time [format] | 各リクエストの現在時刻を出力 |
-J, --json | JSON形式で出力 |
-p, --print-count <count> | <count>リクエストごとに統計出力 |
-P, --print-interval <time> | <time>間隔で統計出力 |
-q, --quiet | 人間可読な出力を抑制 |
-h, --help | ヘルプメッセージを表示して終了 |
-v, --version | バージョンを表示して終了 |
基本的な使い方
シンプルな測定
# 現在のディレクトリでI/Oレイテンシを測定
ioping .# 出力例
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=1 time=173.5 us (warmup)
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=2 time=304.3 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=3 time=252.2 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=4 time=261.5 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=5 time=185.3 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=6 time=182.7 us
^C
--- . (ext4 /dev/sdc 1006.9 GiB) ioping statistics ---
5 requests completed in 1.19 ms, 20 KiB read, 4.22 k iops, 16.5 MiB/s
generated 6 requests in 5.84 s, 24 KiB, 1 iops, 4.11 KiB/s
min/avg/max/mdev = 182.7 us / 237.2 us / 304.3 us / 46.9 us指定回数の測定
# 10回測定して終了
ioping -c 10 .4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=1 time=168.2 us (warmup)
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=2 time=294.8 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=3 time=289.7 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=4 time=281.5 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=5 time=259.6 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=6 time=290.4 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=7 time=2.68 ms (slow)
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=8 time=284.8 us (fast)
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=9 time=263.6 us (fast)
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=10 time=264.2 us (fast)
--- . (ext4 /dev/sdc 1006.9 GiB) ioping statistics ---
9 requests completed in 4.91 ms, 36 KiB read, 1.83 k iops, 7.16 MiB/s
generated 10 requests in 9.00 s, 40 KiB, 1 iops, 4.44 KiB/s
min/avg/max/mdev = 259.6 us / 545.8 us / 2.68 ms / 755.9 us詳細な測定オプション
ブロックサイズの指定
# 1MBでテスト
ioping -s 1M -c 5 .1 MiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=1 time=696.4 us (warmup)
1 MiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=2 time=733.1 us
1 MiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=3 time=769.4 us
1 MiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=4 time=772.4 us
1 MiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=5 time=767.2 us
--- . (ext4 /dev/sdc 1006.9 GiB) ioping statistics ---
4 requests completed in 3.04 ms, 4 MiB read, 1.31 k iops, 1.28 GiB/s
generated 5 requests in 4.00 s, 5 MiB, 1 iops, 1.25 MiB/s
min/avg/max/mdev = 733.1 us / 760.5 us / 772.4 us / 16.0 us間隔の指定
# 0.5秒間隔で測定
ioping -i 0.5 -c 5 .4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=1 time=163.7 us (warmup)
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=2 time=278.9 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=3 time=224.2 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=4 time=296.8 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=5 time=255.5 us
--- . (ext4 /dev/sdc 1006.9 GiB) ioping statistics ---
4 requests completed in 1.06 ms, 16 KiB read, 3.79 k iops, 14.8 MiB/s
generated 5 requests in 2.01 s, 20 KiB, 2 iops, 9.97 KiB/s
min/avg/max/mdev = 224.2 us / 263.8 us / 296.8 us / 27.2 us時間指定での測定
# 10秒間測定
ioping -w 10 .
# 統計のみ表示(-q quiet モード)
ioping -q -w 10 .--- . (ext4 /dev/sdc 1006.9 GiB) ioping statistics ---
9 requests completed in 2.53 ms, 36 KiB read, 3.56 k iops, 13.9 MiB/s
generated 10 requests in 9.02 s, 40 KiB, 1 iops, 4.43 KiB/s
min/avg/max/mdev = 239.3 us / 280.7 us / 343.6 us / 30.5 usシーケンシャルアクセス測定
# シーケンシャルアクセスのテスト
ioping -R -s 1M -c 10 .--- . (ext4 /dev/sdc 1006.9 GiB) ioping statistics ---
9 requests completed in 5.46 ms, 9 MiB read, 1.65 k iops, 1.61 GiB/s
generated 10 requests in 7.19 ms, 10 MiB, 1.39 k iops, 1.36 GiB/s
min/avg/max/mdev = 517.2 us / 606.9 us / 729.9 us / 69.3 usランダムアクセスでの負荷テスト
# ランダムアクセス、高負荷テスト
ioping -D -s 4k -w 30 .# 出力例
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=1 time=225.8 us (warmup)
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=2 time=262.2 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=3 time=300.1 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=4 time=279.2 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=5 time=272.8 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=6 time=305.1 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=7 time=224.9 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=8 time=286.8 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=9 time=276.7 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=10 time=306.1 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=11 time=295.5 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=12 time=292.3 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=13 time=312.7 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=14 time=278.6 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=15 time=305.5 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=16 time=295.3 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=17 time=290.4 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=18 time=294.4 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=19 time=313.6 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=20 time=299.0 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=21 time=281.4 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=22 time=266.7 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=23 time=294.0 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=24 time=319.2 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=25 time=309.6 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=26 time=304.9 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=27 time=308.7 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=28 time=343.9 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=29 time=293.6 us
4 KiB <<< . (ext4 /dev/sdc 1006.9 GiB): request=30 time=289.2 us
--- . (ext4 /dev/sdc 1006.9 GiB) ioping statistics ---
29 requests completed in 8.50 ms, 116 KiB read, 3.41 k iops, 13.3 MiB/s
generated 30 requests in 29.0 s, 120 KiB, 1 iops, 4.13 KiB/s
min/avg/max/mdev = 224.9 us / 293.2 us / 343.9 us / 21.1 us測定シナリオについて考える
データベースワークロード想定
データベースサーバーでは、小さなランダムアクセスが頻繁に発生する。iopingでデータベースディレクトリを対象に測定することで、実際のワークロードに近い条件でI/Oレイテンシを評価できる。
# 小さなランダムアクセス(データベース的)
ioping -R -s 8k -w 60 /var/lib/mysql/8 KiB <<< /var/lib/mysql (ext4 /dev/sda1): request=1 time=125.4 us, random (warmup)
8 KiB <<< /var/lib/mysql (ext4 /dev/sda1): request=2 time=89.7 us, random
8 KiB <<< /var/lib/mysql (ext4 /dev/sda1): request=3 time=95.3 us, random
...
--- /var/lib/mysql (ext4 /dev/sda1) ioping statistics ---
642 requests completed in 60.2 ms, 5.0 MiB read, 10.7 k iops, 85.3 MiB/s
generated 642 requests in 60.0 s, 5.0 MiB, 11 iops, 85.3 KiB/s
min/avg/max/mdev = 78.2 us / 93.8 us / 156.7 us / 8.9 usデータベース測定のオプションについて
- ブロックサイズ: 8KiBはMySQL InnoDBの標準ページサイズ
- ランダムアクセス:
-Rオプションでランダム読み取り - 測定時間: 60秒程度で安定した統計を取得
- 対象ディレクトリ: 実際のデータファイルが配置されているパス
ログファイル書き込み想定
# シーケンシャル書き込み(ログファイル的)
ioping -W -s 64k -w 30 /var/log/
# 出力例
64 KiB >>> /var/log (ext4 /dev/sda1): request=1 time=245.6 us, sequential write (warmup)
64 KiB >>> /var/log (ext4 /dev/sda1): request=2 time=189.3 us, sequential write
64 KiB >>> /var/log (ext4 /dev/sda1): request=3 time=201.7 us, sequential write他のツールとの比較
iostat との比較
# iostat(システム全体のI/O統計)
iostat -x 1 5
# ioping(特定パスのレイテンシ)
ioping -w 5 .fio との比較
# fio(高機能ベンチマーク)
fio --name=random-read --rw=randread --bs=4k --runtime=30 --filename=./testfile
# ioping(シンプルなレイテンシ測定)
ioping -c 30 .| ツール | 用途 | 特徴 |
|---|---|---|
| ioping | レイテンシ測定 | シンプル、リアルタイム |
| iostat | システム全体のI/O統計 | OS標準、継続監視 |
| fio | 詳細なベンチマーク | 高機能、複雑な設定 |
| dd | シンプルなスループット測定 | 標準コマンド、基本的 |
参考
ioping GitHub Repository
https://github.com/koct9i/iopingLinux I/O Performance Tools
https://www.brendangregg.com/Perf/linux_observability_tools.pngStorage Performance Benchmarking
https://www.kernel.org/doc/Documentation/block/ioprio.txtUnderstanding Disk I/O
https://docs.kernel.org/admin-guide/iostats.html
おわりに
今回は、iopingを使ったI/Oレイテンシの測定について学んだ。
特に、データベースサーバーやファイルサーバーでパフォーマンス問題が発生した際、iopingで素早くI/Oレイテンシを確認することで、ストレージがボトルネックかどうかを判断できる。
他のツールとも比較しつつ、iopingも使ってみようかな。