doc_memo/raspberry-and-orange-pi/measuring-performance-storage-devices.md

294 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Измерение скорости накопителей (HDD, SSD, USB Flash, NAS и т.д.) под Linux
Способов измерения скорости накопителей под Linux много, и можно подобрать такие, что более точно покажут
производительность именно на ваших задачах.
## Тесты накопителей с помощью fio
`fio` (Flexible I/O Tester) — мощный инструмент для тестирования производительности систем ввода-вывода (I/O) на
дисках и файловых системах. Он гибко настраивается, поддерживает разные режимы ввода-вывода, размеры блоков,
параллелизм и типы нагрузок. Используется для оценки скорости чтения/записи, задержек и IOPS (число операций
ввода/вывода в секунду).
Установка fio:
```shell
sudo apt install fio
```
Запуск теста (например тест с высокой нагрузкой, эмулирующий многопоточный доступ к диску с небольшими блоками данных):
```shell
fio --name=seq_nvme --size=10G --bs=1M --bs=4k --direct=1 --rw=randrw --rwmixread=70 --numjobs=4 --iodepth=32 --runtime=60
```
Где:
* `--name=seq_nvme` — имя теста.
* `--size=10G` — размер файла для теста (10 ГБ).
* `--bs=1M` — размер блока данных (1 МБ).
* `--bs=4k` — размер блока данных (4 КБ).
* `--direct=1` — обход кэша операционной системы.
* `--rw=randrw` — тип операции (случайное чтение и запись). Также можно установить и другие параметры: `write` — тип операции (последовательная запись). `read` -- последовательное чтение, `randwrite` -- случайная запись, `randread` -- случайное чтение, `rw` -- смешанный режим (чтение и запись).
* `--rwmixread=70` — процент операций чтения/запись (70% чтения, 30% записи).
* `--numjobs=4` — количество потоков (заданий), которые одновременно выполняются.
* `--iodepth=32` — количество операций ввода-вывода, которые отправляются одновременно.
* `--runtime=60` — продолжительность теста (60 секунд), для длинных тестов используйте `--time_based` чтобы тест завершался по времени.
И так далее. Еще есть ключ `--output=test.log` для сохранения результатов в log-файл. Подробнее о параметрах можно посмотреть в справке `man fio` или `fio --help`.
Результаты выполнения вышеуказанной команды для моего NVMe SSD (Kingston SNV2S/2000G) были следующие:
```text
seq_nvme: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=psync, iodepth=32
...
fio-3.28
Starting 4 processes
Jobs: 4 (f=4): [m(4)][100.0%][r=33.4MiB/s,w=15.1MiB/s][r=8550,w=3861 IOPS][eta 00m:00s]
seq_nvme: (groupid=0, jobs=1): err= 0: pid=44678: Fri Nov 29 23:41:45 2024
read: IOPS=2415, BW=9662KiB/s (9894kB/s)(566MiB/60001msec)
clat (usec): min=60, max=41549, avg=298.88, stdev=321.06
lat (usec): min=61, max=41550, avg=300.04, stdev=321.13
clat percentiles (usec):
| 1.00th=[ 76], 5.00th=[ 99], 10.00th=[ 135], 20.00th=[ 165],
| 30.00th=[ 190], 40.00th=[ 225], 50.00th=[ 281], 60.00th=[ 306],
| 70.00th=[ 334], 80.00th=[ 371], 90.00th=[ 420], 95.00th=[ 486],
| 99.00th=[ 1663], 99.50th=[ 1991], 99.90th=[ 2573], 99.95th=[ 3228],
| 99.99th=[ 4490]
bw ( KiB/s): min= 6888, max=12838, per=24.33%, avg=9668.65, stdev=1269.47, samples=119
iops : min= 1722, max= 3209, avg=2417.03, stdev=317.35, samples=119
write: IOPS=1033, BW=4133KiB/s (4232kB/s)(242MiB/60001msec); 0 zone resets
clat (usec): min=19, max=21700, avg=224.76, stdev=261.15
lat (usec): min=19, max=21702, avg=226.79, stdev=261.28
clat percentiles (usec):
| 1.00th=[ 32], 5.00th=[ 33], 10.00th=[ 46], 20.00th=[ 76],
| 30.00th=[ 106], 40.00th=[ 141], 50.00th=[ 174], 60.00th=[ 217],
| 70.00th=[ 293], 80.00th=[ 334], 90.00th=[ 396], 95.00th=[ 453],
| 99.00th=[ 1483], 99.50th=[ 1893], 99.90th=[ 2442], 99.95th=[ 2966],
| 99.99th=[ 4047]
bw ( KiB/s): min= 2784, max= 5516, per=24.23%, avg=4138.13, stdev=561.74, samples=119
iops : min= 696, max= 1379, avg=1034.42, stdev=140.40, samples=119
lat (usec) : 20=0.01%, 50=3.27%, 100=9.03%, 250=38.81%, 500=44.77%
lat (usec) : 750=2.25%, 1000=0.21%
lat (msec) : 2=1.21%, 4=0.44%, 10=0.01%, 20=0.01%, 50=0.01%
cpu : usr=7.75%, sys=19.95%, ctx=206950, majf=0, minf=29
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=144938,61997,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=32
seq_nvme: (groupid=0, jobs=1): err= 0: pid=44679: Fri Nov 29 23:41:45 2024
read: IOPS=2390, BW=9562KiB/s (9791kB/s)(560MiB/60001msec)
clat (usec): min=63, max=22486, avg=293.54, stdev=282.59
lat (usec): min=63, max=22487, avg=294.85, stdev=282.65
clat percentiles (usec):
| 1.00th=[ 94], 5.00th=[ 129], 10.00th=[ 147], 20.00th=[ 165],
| 30.00th=[ 188], 40.00th=[ 217], 50.00th=[ 247], 60.00th=[ 297],
| 70.00th=[ 322], 80.00th=[ 363], 90.00th=[ 416], 95.00th=[ 482],
| 99.00th=[ 1663], 99.50th=[ 2008], 99.90th=[ 2606], 99.95th=[ 3195],
| 99.99th=[ 4359]
bw ( KiB/s): min= 6944, max=13312, per=24.09%, avg=9573.84, stdev=1150.52, samples=119
iops : min= 1736, max= 3328, avg=2393.38, stdev=287.64, samples=119
write: IOPS=1027, BW=4110KiB/s (4209kB/s)(241MiB/60001msec); 0 zone resets
clat (usec): min=20, max=41544, avg=236.88, stdev=347.28
lat (usec): min=21, max=41545, avg=239.32, stdev=347.36
clat percentiles (usec):
| 1.00th=[ 32], 5.00th=[ 41], 10.00th=[ 90], 20.00th=[ 115],
| 30.00th=[ 137], 40.00th=[ 159], 50.00th=[ 186], 60.00th=[ 215],
| 70.00th=[ 277], 80.00th=[ 334], 90.00th=[ 392], 95.00th=[ 453],
| 99.00th=[ 1516], 99.50th=[ 1876], 99.90th=[ 2409], 99.95th=[ 3064],
| 99.99th=[ 4113]
bw ( KiB/s): min= 2904, max= 5680, per=24.10%, avg=4116.52, stdev=533.76, samples=119
iops : min= 726, max= 1420, avg=1029.00, stdev=133.43, samples=119
lat (usec) : 50=1.74%, 100=5.26%, 250=48.61%, 500=40.37%, 750=2.13%
lat (usec) : 1000=0.21%
lat (msec) : 2=1.22%, 4=0.45%, 10=0.01%, 20=0.01%, 50=0.01%
cpu : usr=9.60%, sys=22.32%, ctx=205089, majf=0, minf=31
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=143428,61649,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=32
seq_nvme: (groupid=0, jobs=1): err= 0: pid=44680: Fri Nov 29 23:41:45 2024
read: IOPS=2596, BW=10.1MiB/s (10.6MB/s)(609MiB/60001msec)
clat (usec): min=65, max=40409, avg=284.56, stdev=285.63
lat (usec): min=65, max=40410, avg=285.50, stdev=285.70
clat percentiles (usec):
| 1.00th=[ 75], 5.00th=[ 96], 10.00th=[ 113], 20.00th=[ 159],
| 30.00th=[ 186], 40.00th=[ 206], 50.00th=[ 262], 60.00th=[ 293],
| 70.00th=[ 322], 80.00th=[ 359], 90.00th=[ 404], 95.00th=[ 474],
| 99.00th=[ 1631], 99.50th=[ 1975], 99.90th=[ 2540], 99.95th=[ 3064],
| 99.99th=[ 4146]
bw ( KiB/s): min= 8015, max=14080, per=26.15%, avg=10392.20, stdev=1341.91, samples=119
iops : min= 2003, max= 3520, avg=2597.87, stdev=335.53, samples=119
write: IOPS=1116, BW=4465KiB/s (4572kB/s)(262MiB/60001msec); 0 zone resets
clat (usec): min=24, max=41585, avg=198.90, stdev=319.52
lat (usec): min=25, max=41587, avg=200.53, stdev=319.59
clat percentiles (usec):
| 1.00th=[ 32], 5.00th=[ 32], 10.00th=[ 34], 20.00th=[ 59],
| 30.00th=[ 75], 40.00th=[ 96], 50.00th=[ 145], 60.00th=[ 190],
| 70.00th=[ 269], 80.00th=[ 314], 90.00th=[ 375], 95.00th=[ 429],
| 99.00th=[ 1369], 99.50th=[ 1795], 99.90th=[ 2376], 99.95th=[ 2999],
| 99.99th=[ 4490]
bw ( KiB/s): min= 3401, max= 5984, per=26.16%, avg=4468.75, stdev=561.75, samples=119
iops : min= 850, max= 1496, avg=1117.05, stdev=140.43, samples=119
lat (usec) : 50=5.17%, 100=12.96%, 250=36.62%, 500=41.68%, 750=1.84%
lat (usec) : 1000=0.19%
lat (msec) : 2=1.12%, 4=0.41%, 10=0.01%, 20=0.01%, 50=0.01%
cpu : usr=6.73%, sys=17.26%, ctx=222857, majf=0, minf=29
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=155819,66981,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=32
seq_nvme: (groupid=0, jobs=1): err= 0: pid=44681: Fri Nov 29 23:41:45 2024
read: IOPS=2531, BW=9.89MiB/s (10.4MB/s)(593MiB/60000msec)
clat (usec): min=60, max=41793, avg=282.72, stdev=305.59
lat (usec): min=60, max=41794, avg=283.89, stdev=305.67
clat percentiles (usec):
| 1.00th=[ 76], 5.00th=[ 98], 10.00th=[ 131], 20.00th=[ 159],
| 30.00th=[ 184], 40.00th=[ 200], 50.00th=[ 237], 60.00th=[ 285],
| 70.00th=[ 318], 80.00th=[ 355], 90.00th=[ 408], 95.00th=[ 474],
| 99.00th=[ 1631], 99.50th=[ 1975], 99.90th=[ 2540], 99.95th=[ 3064],
| 99.99th=[ 4178]
bw ( KiB/s): min= 7624, max=14408, per=25.52%, avg=10140.96, stdev=1641.40, samples=119
iops : min= 1906, max= 3602, avg=2535.13, stdev=410.35, samples=119
write: IOPS=1092, BW=4369KiB/s (4474kB/s)(256MiB/60000msec); 0 zone resets
clat (usec): min=19, max=22481, avg=214.85, stdev=280.81
lat (usec): min=19, max=22483, avg=216.97, stdev=280.96
clat percentiles (usec):
| 1.00th=[ 31], 5.00th=[ 32], 10.00th=[ 37], 20.00th=[ 77],
| 30.00th=[ 113], 40.00th=[ 139], 50.00th=[ 165], 60.00th=[ 196],
| 70.00th=[ 251], 80.00th=[ 322], 90.00th=[ 383], 95.00th=[ 445],
| 99.00th=[ 1467], 99.50th=[ 1844], 99.90th=[ 2442], 99.95th=[ 3032],
| 99.99th=[ 4490]
bw ( KiB/s): min= 3192, max= 6072, per=25.61%, avg=4373.76, stdev=743.54, samples=119
iops : min= 798, max= 1518, avg=1093.28, stdev=185.89, samples=119
lat (usec) : 20=0.01%, 50=4.00%, 100=8.72%, 250=45.79%, 500=37.74%
lat (usec) : 750=1.97%, 1000=0.19%
lat (msec) : 2=1.16%, 4=0.41%, 10=0.01%, 20=0.01%, 50=0.01%
cpu : usr=8.77%, sys=20.44%, ctx=217410, majf=0, minf=32
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=151861,65532,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=32
Run status group 0 (all jobs):
READ: bw=38.8MiB/s (40.7MB/s), 9562KiB/s-10.1MiB/s (9791kB/s-10.6MB/s), io=2328MiB (2441MB), run=60000-60001msec
WRITE: bw=16.7MiB/s (17.5MB/s), 4110KiB/s-4465KiB/s (4209kB/s-4572kB/s), io=1001MiB (1049MB), run=60000-60001msec
Disk stats (read/write):
nvme0n1: ios=594831/255707, merge=0/0, ticks=134992/39009, in_queue=174001, util=100.00%
```
Разберем результаты выполнения вашего fio-теста о основным метрикам и объясним их значение.
#### Общий результат (Run status group 0):
* Чтение (READ):
* Скорость: 38.8 MiB/s (40.7 MB/s) — средняя скорость чтения всех заданий.
* Диапазон: 9562 KiB/s - 10.1 MiB/s — скорости отдельных потоков.
* Объем данных: 2328 MiB (около 2.44 GB).
* Запись (WRITE):
* Скорость: 16.7 MiB/s (17.5 MB/s).
* Диапазон: 4110 KiB/s - 4465 KiB/s.
* Объем данных: 1001 MiB (около 1.049 GB).
#### Метрики на потоки
Для каждого потока представлены следующие данные:
* Чтение (READ)
* IOPS -- Средние значения IOPS (операции в секунду) для потоков составляют, например, 2415 IOPS для первого задания. Это число показывает, сколько операций чтения в секунду выполнялось.
* Latency (задержка) -- Время отклика операций ввода-вывода (чтение). Например, среднее время отклика (clat) составляет 298.88 микросекунд, а 99-й процентиль (99.00th) — 1663 микросекунды. Это означает, что 99% операций чтения завершаются за это время.
* Bandwidth (пропускная способность) -- Средние скорости чтения: 9.66 MiB/s, 9.57 MiB/s и т.д.
* Запись (WRITE)
* IOPS -- Средние значения: около 1033-1117 IOPS. Меньше, чем для чтения из-за меньшего процента операций записи.
* Latency (задержка) -- Средняя задержка: около 200-230 микросекунд. Процентиль 99%: до 1483-4490 микросекунд.
* Bandwidth (пропускная способность) -- Средняя скорость записи: 4.1-4.4 MiB/s.
#### Сводка задержек (Latency Summary)
* Чтение: 50% операций завершались за ~281 микросекунду (медиана). 99.5% операций — за менее чем 1991 микросекунду.
* Запись:- 50% операций завершались за ~174-186 микросекунд. 99% — менее чем за 1467 микросекунд.
#### Нагрузка на диск (Disk Utilization)
* Число операций: 594831 операций чтения и 255707 операций записи. Диск был загружен на 100% времени, что ожидаемо для высокой глубины очереди (iodepth=32).
#### Общие выводы
Для случайных операций на маленьких блоках (4 КБ) Kingston SNV2S/2000G демонстрирует хорошую производительность (средние 40.7 MB/s чтения и 17.5 MB/s записи). IOPS соответствуют значениям для высокопроизводительных NVMe SSD. Средние задержки в районе 200-300 микросекунд — это нормально для NVMe. Процентиль 99% показывает стабильность: отклонения есть, но они незначительны. Полная загрузка диска (util=100%) свидетельствует о том, что диск эффективно обрабатывает запросы в рамках установленной глубины очереди.
-----
## Измерение задержек (latency) операций ввода/вывода
Утилита ioping проверяет задержки накопителей данных (похож на ping, но для дисков).
Установим ioping:
```shell
sudo apt install ioping
```
Замер:
```shell
ioping -c 10 -s 1m -W .
```
Где:
* `-c 10` — количество замеров;
* `-s 10m` — размер блока данных для тестирования. `10m` — 10 мегабайт. В целом `ioping` — это тест производительности дисковой подсистемы, через измерения задержек при доступе к небольшим блокам данных (обычно 4 KiB). Но отлично работает и на больших блоках, оказывая производительность диска в целом.
* `-W`С записью вместо чтения. Это более безопасно для временного файла в целевом каталоге, и, кроме того, запись ввода-вывода даёт более надежные результаты для систем, где некэшированные чтения не поддерживаются
или происходит искажающее замеры кэширование на каком-то уровне.
* `.` — каталог, в котором будут производиться замеры. `.` — текущий каталог.
Другие ключи и опции можно посмотреть в справке `man ioping` или `ioping --help`.
Результаты теста будут примерно такими:
```text
10 MiB >>> . (ext4 /dev/nvme0n1p2 1.79 TiB): request=1 time=21.1 ms (warmup)
10 MiB >>> . (ext4 /dev/nvme0n1p2 1.79 TiB): request=2 time=29.7 ms
10 MiB >>> . (ext4 /dev/nvme0n1p2 1.79 TiB): request=3 time=23.5 ms
10 MiB >>> . (ext4 /dev/nvme0n1p2 1.79 TiB): request=4 time=22.3 ms
10 MiB >>> . (ext4 /dev/nvme0n1p2 1.79 TiB): request=5 time=21.7 ms
10 MiB >>> . (ext4 /dev/nvme0n1p2 1.79 TiB): request=6 time=23.1 ms
10 MiB >>> . (ext4 /dev/nvme0n1p2 1.79 TiB): request=7 time=21.7 ms (fast)
10 MiB >>> . (ext4 /dev/nvme0n1p2 1.79 TiB): request=8 time=31.1 ms (slow)
10 MiB >>> . (ext4 /dev/nvme0n1p2 1.79 TiB): request=9 time=23.0 ms
10 MiB >>> . (ext4 /dev/nvme0n1p2 1.79 TiB): request=10 time=22.7 ms
--- . (ext4 /dev/nvme0n1p2 1.79 TiB) ioping statistics ---
9 requests completed in 218.8 ms, 90 MiB written, 41 iops, 411.3 MiB/s
generated 10 requests in 9.04 s, 100 MiB, 1 iops, 11.1 MiB/s
min/avg/max/mdev = 21.7 ms / 24.3 ms / 31.1 ms / 3.32 ms
```
Сверху выводятся данные по индивидуальным запросам:
```text
10 MiB >>> . (ext4 /dev/nvme0n1p2 1.79 TiB): request=1 time=21.1 ms (warmup)
```
Где:
* `10 MiB` — размер блока данных, к которому идет доступ;
* `<<< .` — текущая директория, на которой проводится тест;
* `(ext4 /dev/nvme0n1p2 1.79 TiB)` — файловая система (ext4) и устройство (/dev/nvme0n1p2) с емкостью 1.79 ТБ, где выполняется тест;
* `request=1` — номер запроса;
* `time=21.1 ms` — время выполнения запроса (в миллисекундах — `ms`, в микросекунды — `us`);
* `(warmup)` — первый запрос может использоваться для "прогрева", его результаты могут быть исключены из финальной статистики, `(fast)` — запрос выполнен быстрее, чем среднее время выполнения, `(slow)` — запрос выполнен медленнее, чем среднее время выполнения.
Снизу выводятся статистические данные по всем запросам:
```text
9 requests completed in 218.8 ms, 90 MiB written, 41 iops, 411.3 MiB/s
generated 10 requests in 9.04 s, 100 MiB, 1 iops, 11.1 MiB/s
min/avg/max/mdev = 21.7 ms / 24.3 ms / 31.1 ms / 3.32 ms
```
Где:
* `9 requests completed in 218.8 ms` — количество запросов, завершенных за время теста и общее время выполнения;
* `90 MiB written` — общий объем данных, записанных на диск;
* `41 iops` — количество операций ввода/вывода в секунду (IOPS);
* `411.3 MiB/s` — скорость записи данных на диск;
* `generated 10 requests in 9.04 s` — количество запросов, сгенерированных за время теста и общее время выполнения;
* `100 MiB` — общий объем данных, сгенерированных тестом;
* `1 iops` — количество операций ввода/вывода в секунду (IOPS) при генерации данных;
* `11.1 MiB/s` — скорость генерации данных;
* `min/avg/max/mdev = 21.7 ms / 24.3 ms / 31.1 ms / 3.32 ms`**минимальное**, **среднее**, **максимальное** задержка выполнения запросов и **стандартное отклонение**, показатель того, насколько задержки разнятся между запросами.