Разбор высокой I/O-задержки (I/O Wait) в Linux

Разбор высокой I/O-задержки (I/O Wait) в Linux


У Linux куча инструментов для диагностики — какие-то простые, а какие-то посерьёзнее. Проблемы с I/O Wait как раз из тех случаев, где нужны продвинутые утилиты и умение выжать максимум даже из базовых инструментов.

Разбираться с I/O Wait непросто, потому что в стандартной поставке есть масса средств, которые могут сказать вам одно: система упирается в ввод-вывод, и что-то не так.

Но вот pinpoint-ить конкретный процесс (или несколько), который всё тормозит, — умеют далеко не все.

Определяем, виноват ли I/O в том, что система тормозит

Есть несколько способов понять, вызывает ли медлительность системы именно ввод-вывод, но самый простой — команда top.

В строке CPU(s) видно, как загружен процессор и на что уходит его время.

В приведённом выше примере видно, что процессор 96% времени просто ждёт, пока завершится доступ к устройствам ввода-вывода. Это показатель wa (wait), который, как указано в man-странице top, означает «время, которое CPU проводит в ожидании завершения операций ввода-вывода».

Определяем, на какой диск идёт нагрузка

В примере выше команда top показывает общую I/O-задержку по системе, но не говорит, какой именно диск страдает. Чтобы это выяснить, используем iostat.

$ iostat -x 2 5
 avg-cpu: %user %nice %system %iowait %steal %idle
  3.66 0.00 47.64 48.69 0.00 0.00
 
 Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
 sda 44.50 39.27 117.28 29.32 11220.94 13126.70 332.17 65.77 462.79 9.80 2274.71 7.60 111.41
 dm-0 0.00 0.00 83.25 9.95 10515.18 4295.29 317.84 57.01 648.54 16.73 5935.79 11.48 107.02
 dm-1 0.00 0.00 57.07 40.84 228.27 163.35 8.00 93.84 979.61 13.94 2329.08 10.93 107.02

В приведённой команде iostat выводит отчёт каждые 2 секунды, всего 5 раз. Ключ -x включает расширенный отчёт.

Первый отчёт iostat показывает статистику с момента последней загрузки системы — поэтому его обычно можно просто проигнорировать. Все последующие отчёты показывают данные за интервал с момента предыдущего.

Например, если мы просим вывести отчёт 5 раз, то второй будет собран на основе изменений после первого, третий — после второго и так далее.

В нашем примере видно, что процент использования диска sda111.41%, что явно указывает: проблема связана с процессами, активно пишущими на sda.

В тестовой системе из примера всего один диск, но такая информация особенно полезна, если дисков несколько — это помогает сузить круг поиска до конкретного устройства, которое загружено I/O-операциями.

Кроме процента использования, в выводе iostat есть масса полезных метрик: количество объединённых запросов чтения и записи в миллисекунду (rrqm/s и wrqm/s), операции чтения и записи в секунду (r/s и w/s) и многое другое.

В нашем случае программа активно и читает, и пишет, — и эта информация пригодится, когда будем искать конкретный процесс, создающий нагрузку.

Определяем процессы, которые создают высокую I/O-нагрузку

Отличный инструмент, чтобы понять, какие процессы активно работают с диском, — это iotop.

# iotop
 Total DISK READ: 8.00 M/s | Total DISK WRITE: 20.36 M/s
  TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
 15758 be/4 root 7.99 M/s 8.01 M/s 0.00 % 61.97 % bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp

Посмотрев на его вывод, сразу видно, что программа bonnie++ больше всех грузит подсистему ввода-вывода на этой машине.

Хотя iotop прост в использовании и действительно удобен, он по умолчанию установлен далеко не во всех (а часто и вовсе не в основных) дистрибутивах Linux. Лично я стараюсь не полагаться на утилиты, которых нет «из коробки».

Системный администратор может оказаться в ситуации, когда нельзя поставить дополнительные пакеты до запланированного окна обслуживания или завершения важного процесса — а к тому времени проблема может стать уже критичной.

Если iotop недоступен, не страшно: шаги ниже помогут сузить поиск и без него — до одного или нескольких процессов, создающих нагрузку.

Состояние процессов (“state”)

Команду ps знают почти все, но не все догадываются, что она умеет показывать статистику по памяти и CPU.

К сожалению, отдельной метрики для дискового ввода-вывода у неё нет, но зато она отображает состояние процесса — и по нему можно понять, ждёт ли процесс операций I/O.

Поле state в выводе ps даёт наглядное представление о том, чем занят процесс в данный момент. Чтобы было понятнее, разберём возможные состояния по man-странице ps:

D: uninterruptible sleep (обычно связано с I/O)
R: running или runnable (в очереди на выполнение)
S: interruptible sleep (ждёт завершения какого-то события)
T: stopped (остановлен сигналом управления задачами или трассировкой)
W: paging (устаревшее, не используется со времён ядра 2.6.xx)
X: dead (мертвый процесс, не должен появляться)
Z: defunct ("зомби" — завершён, но не убран родительским процессом)

Процессы, застрявшие в ожидании I/O, чаще всего находятся в состоянии D (uninterruptible sleep).

Зная это, можно легко вычислить процессы, которые постоянно висят в этом состоянии — при помощи пары строк на Bash.

 # for x in `seq 1 1 10`; do ps -eo state,pid,cmd | grep "^D"; echo "----"; sleep 5; done
 D 248 [jbd2/dm-0-8]
 D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp
 ----
 D 22 [kswapd0]
 D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp
 ----
 D 22 [kswapd0]
 D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp
 ----
 D 22 [kswapd0]
 D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp
 ----
 D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp
 ----

Этот цикл for выводит список процессов, находящихся в состоянии D, каждые 5 секунд, всего 10 раз.

Из результата видно, что процесс bonnie++ с PID 16528 чаще других оказывается в ожидании I/O.

На этом этапе можно предположить, что именно он вызывает повышенный I/O Wait. Но важно понимать: сам по себе факт, что процесс находится в состоянии uninterruptible sleep, ещё не доказывает, что именно он виноват в задержках ввода-вывода.

Чтобы подтвердить догадку, можно воспользоваться файловой системой /proc.

У каждого процесса в каталоге /proc/<pid>/ есть файл io, который содержит статистику по I/O — ту же самую, что использует iotop.

# cat /proc/16528/io
rchar: 48752567
wchar: 549961789
syscr: 5967
syscw: 67138
read_bytes: 49020928
write_bytes: 549961728
cancelled_write_bytes:

Поля read_bytes и write_bytes показывают, сколько байт конкретный процесс прочитал и записал на устройство хранения.

В нашем случае процесс bonnie++ прочитал около 46 МБ и записал 524 МБ.

Для некоторых программ это мелочь, но в нашем примере этого объёма достаточно, чтобы создать ту самую высокую I/O-задержку, которую мы наблюдаем в системе.

Определяем, какие файлы перегружаются записью

Когда мы уже нашли подозрительный процесс (или несколько), можно использовать команду lsof, чтобы посмотреть, какие файлы этот процесс держит открытыми.

Список открытых файлов позволит прикинуть, какие из них чаще всего подвергаются записи.

В примере ниже вывод lsof отфильтрован с помощью флага -p <pid>, который показывает только файлы, открытые конкретным процессом:

# lsof -p 16528
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
bonnie++ 16528  root   cwd  DIR  252,0     4096   130597 /tmp
<truncated>
bonnie++ 16528  root   8u   REG  252,0 501219328   131869 /tmp/Bonnie.16528
bonnie++ 16528  root   9u   REG  252,0 501219328   131869 /tmp/Bonnie.16528
bonnie++ 16528  root  10u   REG  252,0 501219328   131869 /tmp/Bonnie.16528
bonnie++ 16528  root  11u   REG  252,0 501219328   131869 /tmp/Bonnie.16528
bonnie++ 16528  root  12u   REG  252,0 501219328   131869 /tmp/Bonnie.16528

Чтобы убедиться, что именно эти файлы активно пишутся, можно посмотреть, на каком диске находится файловая система /tmp:

# df /tmp
Filesystem                     1K-blocks    Used  Available  Use%  Mounted on
/dev/mapper/workstation-root     7667140  2628608   4653920   37%  /

Из этого вывода видно, что /tmp — часть корневого логического тома (workstation-root) в группе томов workstation.

Проверим, где физически расположен этот том:

# pvdisplay
--- Physical volume ---
PV Name               /dev/sda5
VG Name               workstation
PV Size               7.76 GiB / not usable 2.00 MiB
Allocatable           yes
PE Size               4.00 MiB
Total PE              1986
Free PE               8
Allocated PE          1978
PV UUID               CLbABb-GcLB-l5z3-TCj3-IOK3-SQ2p-RDPW5S

Из вывода pvdisplay видно, что раздел /dev/sda5 (часть диска sda) используется группой томов workstation, а значит, именно там лежит файловая система /tmp.

С учётом всей этой информации можно с уверенностью сказать: большие файлы, показанные в выводе lsof выше, и есть те самые, к которым процесс bonnie++ постоянно обращается для чтения и записи.


Report Page