odmin@opslog: ~/blog
← cd ..
odmin@opslog:~/blog$ cat top.md

Понимание утилиты top

Утилита top предназначена для мониторинга состояния процессов и системы в целом.

1. Первая строка

bash
top - 13:23:48 up 7 days,  1:47, 23 users,  load average: 0.64, 0.55, 0.56

В первой строке указаны текущее время, время работы системы с момента загрузки, количество вошедших в систему пользователей и средняя загрузка. Средняя загрузка — важный показатель, характеризующий количество задач, готовых к выполнению или находящихся в непрерываемом ожидании. Это не прямой показатель загрузки процессора: например, высокое значение может быть связано с ожиданием операций ввода-вывода. Значение рассчитывается за 1, 5 и 15 минут. На однопроцессорной системе устойчивое значение выше 1 означает, что в среднем задач больше, чем процессор способен одновременно обслужить; на многопроцессорной системе показатель следует сопоставлять с количеством логических процессоров.

В приведённом примере средняя загрузка ниже 1, однако это само по себе не гарантирует отсутствия задержек: необходимо учитывать число процессоров, память, ввод-вывод и характеристики конкретной нагрузки.

Попробуем изменить эти параметры:

bash
yes > /dev/null &

Запустите несколько таких процессов. Команда создаёт процесс, который бесконечно записывает строку y в /dev/null, создавая нагрузку на CPU. Я запустил восемь процессов; в результате значение изменилось:

bash
top - 15:44:13 up 7 days,  4:08, 23 users,  load average: 7.71, 3.50, 1.82

Отзывчивость системы может снизиться. Восемь процессов создают конкуренцию за процессорное время:

img.png

Завершить их можно командой pkill yes.

2. Вторая строка

bash
Tasks: 219 total,   2 running, 217 sleeping,   0 stopped,   0 zombie

Здесь указано общее количество задач, а также количество задач в состояниях выполнения, сна, остановки и зомби. В зависимости от режима top под задачами могут пониматься процессы или потоки.

В данном примере в системе существует 219 задач, 2 из них выполняются или готовы к выполнению, а 217 находятся в состоянии сна. Состояние sleeping не обязательно означает ожидание освобождения ресурса: процесс может ожидать событие, таймер или сигнал. Две последние ячейки показывают отсутствие остановленных процессов и зомби. Зомби — это завершившийся процесс, запись о котором сохраняется до тех пор, пока родительский процесс не получит его статус завершения с помощью wait() или аналогичного вызова. Создадим процесс-зомби и посмотрим, как он отображается в top. Для этого воспользуемся следующим примером:

c
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main (void)
{
  pid_t child_pid = fork ();
  if (child_pid > 0) {
    sleep (60);
  } else if (child_pid == 0) {
    _exit (0);
  } else {
    return EXIT_FAILURE;
  }
  return 0;
}

Сохраните программу в файл z.c и скомпилируйте её:

bash
gcc z.c -o z

Запустите программу:

bash
./z

Проверьте вывод top:

bash
Tasks: 367 total,   1 running, 365 sleeping,   0 stopped,   1 zombie

Появившийся процесс-зомби также можно увидеть с помощью ps:

bash
ps ajx | grep -w Z
22844 22845 22844 24581 pts/21   22844 Z+    1000   0:00 [z]

3. Третья строка

bash
%Cpu(s):  3.4 us,  1.2 sy,  0.0 ni, 94.9 id,  0.1 wa,  0.2 hi,  0.2 si,  0.0 st

Значения загрузки CPU: Первое значение (us) — время выполнения пользовательских процессов без изменения приоритета, второе (sy) — время выполнения кода ядра. Третье значение (ni) — время выполнения пользовательских процессов с изменённым значением nice. Четвёртый параметр (id) показывает время простоя CPU. Пятый параметр (wa) указывает время ожидания завершения операций ввода-вывода. Его следует рассматривать вместе с другими метриками: само по себе это значение не доказывает низкую производительность дисковой подсистемы. Шестой параметр (hi) показывает время обработки аппаратных прерываний, а седьмой (si) — время обработки программных прерываний. Их рост может быть связан, например, с высокой сетевой нагрузкой, но не является прямым признаком аппаратной неисправности. Восьмой параметр (st) указывает время, отнятое гипервизором у виртуальной машины.

Рассмотрим, как изменяются эти параметры под нагрузкой.

Используем утилиту stress.

bash
sudo dnf install stress

Изменим параметр, показывающий загрузку в пользовательском контексте

bash
stress --cpu 8 --timeout 60s

Я запустил восемь рабочих процессов, поскольку в системе восемь логических процессоров. Пример вывода top:

bash
%Cpu(s): 99.0 us,  0.7 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.2 hi,  0.0 si,  0.0 st

Как видим, сразу выросло значение us, поскольку нагрузка выполняется в пользовательском пространстве. Параметр --vm создаёт нагрузку на подсистему памяти:

bash
stress --vm 8 --timeout 60s

Такая нагрузка может увеличить как пользовательское, так и системное время. Конкретное соотношение зависит от версии stress, параметров запуска и системы; нельзя заранее гарантировать конкретные значения sy, hi и si.

bash
%Cpu(s): 14.6 us, 84.6 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.6 hi,  0.1 si,  0.0 st

Запустим stress с повышенным приоритетом. Будьте осторожны: команда может существенно ухудшить отзывчивость системы на 60 секунд:

bash
sudo nice -n -20 stress --cpu 8 --timeout 60s

Теперь запустим процесс с пониженным приоритетом:

bash
sudo nice -n 1 stress --cpu 8 --timeout 60s

img_1.png

Данную команду не обязательно запускать от суперпользователя, поскольку понижение приоритета обычно не требует прав root. В поле ni отображается время, использованное процессами с изменённым значением nice, включая как повышенный, так и пониженный приоритет.

img_2.png

Поле us относится к процессам без изменения приоритета, а ni — к процессам с изменённым значением nice. Отрицательные значения nice соответствуют более высокому приоритету, положительные — более низкому. Рассмотрим нагрузку на ввод-вывод:

bash
stress --io 80 --vm-bytes 512MB --vm-stride 8182 --timeout 60s

Нагружаем ввод-вывод и получаем, например, такое изменение (22.1 wa):

bash
%Cpu(s):  5.3 us, 55.1 sy,  0.0 ni, 14.7 id, 22.1 wa,  1.0 hi,  1.9 si,  0.0 st

Видно, что одновременно с sy выросло ожидание wa. В зависимости от реализации stress нагрузка --io может выполнять sync(), а нагрузка --hdd — создавать записи и удаления файлов. Это позволяет получить высокое wa, но не означает, что процессор занят обработкой диска: он в основном ожидает завершения ввода-вывода. Попробуем нагрузить дисковую подсистему:

bash
stress --hdd 80 --timeout 60s

Видно существенное увеличение времени ожидания ввода-вывода:

bash
%Cpu(s):  8.9 us,  3.7 sy,  0.0 ni,  0.0 id, 86.7 wa,  0.0 hi,  0.7 si,  0.0 st

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

4. Четвёртая и пятая строки

text
MiB Mem :  31963.1 total,   7117.7 free,   8407.1 used,  16438.3 buff/cache
MiB Swap:  12212.0 total,   4322.1 free,   7889.9 used.  22665.2 avail Mem

Здесь отображается состояние оперативной памяти и swap. В данном примере установлено около 32 ГиБ RAM. По умолчанию значения показываются в мебибайтах; масштаб можно изменить, запустив top с параметром -E и указав одно из следующих значений:

text
k - kibibytes
m - mebibytes
g - gibibytes
t - tebibytes
p - pebibytes
e - exbibytes

7117.7 free указывает, что около 7 ГиБ памяти полностью свободно. 8407.1 used — это total - avail Mem, а не объём памяти, выделенный непосредственно программам. 16438.3 buff/cache — буферы, файловый кэш и часть освобождаемой памяти ядра. Кэш может быть освобождён при необходимости, поэтому его большое значение само по себе не свидетельствует о нехватке памяти. Принудительно очищать кэш обычно не требуется: это может ухудшить производительность. Если очистка необходима для контролируемого эксперимента, сначала синхронизируйте данные:

bash
sync
echo 3 | sudo tee /proc/sys/vm/drop_caches

Swap: total, free и used показывают общий, свободный и занятый объём пространства подкачки. Активное перемещение страниц между RAM и swap действительно может значительно снизить отзывчивость системы, однако сам факт использования swap ещё не означает проблему. 4322.1 free и 7889.9 used — свободный и занятый объём swap. 22665.2 avail Mem показывает оценку объёма физической памяти, доступного для запуска новых приложений без обращения к swap. Показатель учитывает свободную память и часть кэшей и освобождаемой памяти; swap в него не входит.

5. Список процессов

Список состоит из столбцов, в которых указаны параметры процессов и используемые ими ресурсы.

bash
PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND

PID — идентификатор процесса. USER — пользователь, от имени которого выполняется процесс. PR — приоритет, отображаемый планировщиком. Значение rt означает использование политики реального времени. NI — значение nice, влияющее на приоритет процесса; обычно диапазон составляет от -20 до 19.

Далее идут столбцы, описывающие использование памяти. В Linux различают физическую память, пространство подкачки и виртуальную память. Виртуальная память обеспечивает независимые адресные пространства процессов, изоляцию и совместное отображение страниц. Упрощённая классификация памяти процесса приведена ниже:

| | Приватная | Общая | |-----------|-------------------------------------------------|-------| | Анонимная | stack <br> malloc() <br> brk()/sbrk()<br> mmap(PRIVATE, ANON) |POSIX shm* <br> mmap(SHARED, ANON)| | Файловая | mmap(PRIVATE, fd)<br>программы и общие библиотеки | mmap(SHARED, fd) |

VIRT — весь объём виртуального адресного пространства процесса, включая используемые и зарезервированные области. RES — объём физической памяти процесса, находящейся в данный момент в RAM; в современных версиях top он складывается из столбцов RSan, RSfd и RSsh (их можно включить клавишей f).

text
RSan — резидентная анонимная память.
RSfd — резидентная файловая память.
RSsh — резидентная общая память.

SHR — приблизительный объём резидентной памяти, которая может быть общей для нескольких процессов. Поэтому выражение RES - SHR не всегда точно соответствует приватной памяти: общие библиотеки и другие страницы могут учитываться особым образом.

Для приблизительной оценки приватной резидентной памяти можно использовать RES - SHR, но это значение не всегда точно. При необходимости добавьте столбец RSan в настройках top.

Состояние процесса в столбце S может иметь следующие значения:

text
D - непрерываемое ожидание, обычно связанное с вводом-выводом
I - бездействующий поток ядра
R - выполняется или готов к выполнению
S - прерываемый сон
T - остановлен сигналом
t - остановлен отладчиком во время трассировки
Z - зомби

%CPU — доля процессорного времени, использованная процессом с момента последнего обновления экрана. В многопроцессорной системе в режиме Irix один многопоточный процесс может показывать значение выше 100 %. Клавиша H переключает отображение процессов и потоков, а клавиша I — режим расчёта, в котором значение нормируется на общее число CPU. %MEM — доля физической памяти, соответствующая значению RES. TIME+ — суммарное процессорное время, использованное задачей с момента запуска. COMMAND — имя программы или командная строка процесса; отображаемый вариант переключается клавишей c.

Дополнительные столбцы можно выбрать клавишей f.

Таким образом, top предоставляет оперативную информацию о состоянии системы и процессов, полезную для первичного анализа производительности и диагностики проблем. Для подробного анализа его показатели следует сопоставлять с данными специализированных инструментов и учитывать особенности конкретной версии ядра и procps.