Как проверить переключение контекста в Linux
В предыдущей статье мы обсудили принцип работы переключений контекста CPU. Кратко резюмируя, переключение контекста CPU — это основная функция, которая обеспечивает нормальную работу системы Linux. Его можно разделить на переключения контекста процесса, переключения контекста потока и переключения контекста прерывания на основе различных сценариев.
Подписывайтесь на канал usr_bin, где я публикую много полезного по Linux, в том числе ссылки на статьи в этом блоге.
В этой статье мы продолжим изучать, как анализировать проблемы, связанные с переключением контекста CPU.
Как просмотреть системные контекстные переключатели
Слишком большое количество переключений контекста может привести к высокому потреблению процессорного времени на сохранение и восстановление данных, таких как регистры, стеки ядра и виртуальная память, тем самым сокращая фактическое время выполнения процессов и становясь основной причиной снижения производительности системы.
В статье мы будем использовать инструмент vmstat
для вывода переключений контекста системы.
vmstat
— это инструмент анализа производительности системы, в основном применяемый для анализа использования памяти системой, а также для анализа количества переключений контекста CPU и прерываний.
Например, вот пример использования vmstat
:
# вывод 1 набора данных каждые 5 секунд $ vmstat 5 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 7005360 91564 818900 0 0 0 0 25 33 0 0 100 0 0
Вот четыре столбца, которые требуют особого внимания:
cs
(переключение контекста) — количество переключений контекста в секунду.in
(прерывание) — количество прерываний в секунду.r
(запущено) — длина очереди выполнения, т. е. количество процессов, которые в данный момент запущены или ожидают CPU.b
(заблокировано) — количество процессов, находящихся в состоянии непрерывного сна.
В этом примере видно, что количество переключений контекста cs
равно 33, а количество прерываний in
— 25 в секунду. Длина очереди выполнения r
и количество процессов в состоянии непрерывного сна b
равны 0.
vmstat
предоставляет обзор ситуации переключения контекста системы. Если вы хотите изучить подробную информацию о переключении контекста для каждого процесса, можено использовать pidstat
. Добавив опцию -w
, вы можете просмотреть информацию о переключении контекста для каждого процесса.
# вывод 1 набора данных каждые 5 секунд $ pidstat -w 5 Linux 4.15.0 (ubuntu) 09/23/18 _x86_64_ (2 CPU) 08:18:26 UID PID cswch/s nvcswch/s Command 08:18:31 0 1 0.20 0.00 systemd 08:18:31 0 8 5.40 0.00 rcu_sched ...
В этом результате есть два столбца, на которых мы в первую очередь сосредоточены. Один из них — cswch
, который представляет количество произвольных переключений контекста в секунду, а другой — nvcswch
, который представляет количество непроизвольных переключений контекста в секунду.
Крайне важно запомнить эти два понятия, поскольку они указывают на разные проблемы с производительностью:
- Добровольные переключения контекста — это переключения контекста, которые происходят, когда процесс не может получить требуемые ресурсы, например, из-за нехватки ввода-вывода или памяти.
- Недобровольные переключения контекста происходят, когда процесс принудительно запланирован системой по таким причинам, как истечение его временного среза. Это часто происходит, когда между процессами идет интенсивная конкуренция за CPU.
Рассмотрим пример
Понимая, как проверить эти метрики, возникает еще один вопрос: что считается нормальной частотой переключений контекста? Не торопитесь с ответом. Давайте сначала рассмотрим пример переключения контекста.
Подготовка
Для моделирования ситуации чрезмерного переключения контекста в системе используется sysbench
.
Перед началом откроем три терминала на одной и той же машине Linux, а также установим два упомянутых выше пакета программного обеспечения.
После установки, можно при помощи vmstat
проверить количество переключений контекста в неактивной системе:
# вывод 1 набора данных каждую секунду $ vmstat 1 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 6984064 92668 830896 0 0 2 19 19 35 1 0 99 0 0
Здесь можно видеть, что текущее количество переключений контекста cs
равно 35, тогда как количество прерываний in
равно 19, а оба значения r
и b
равны 0. Поскольку в данный момент не запущено никаких других задач, это количество переключений контекста для бездействующей системы.
Далее приступим к практической работе.
Сначала запустим sysbench
в первом терминале, чтобы смоделировать узкое место многопоточного планирования системы:
# запустим тест производительности с 10 потоками на 5 минут, чтобы смоделировать проблему переключения нескольких потоков $ sysbench --threads=10 --max-time=300 threads run
Далее запустим vmstat
во втором терминале, чтобы понаблюдать за ситуацией переключения контекста:
# выводим 1 набор данных каждую секунду (используйте Ctrl+C для остановки) $ vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 6 0 0 6487428 118240 1292772 0 0 0 0 9019 1398830 16 84 0 0 0 8 0 0 6487428 118240 1292772 0 0 0 0 10191 1392312 16 84 0 0 0
Заметно, что количество переключений контекста в столбце cs резко возросло с 35 до 1,39 млн. Также обратите внимание на следующие показатели:
- Столбец r: Длина очереди выполнения достигла 8, что намного превышает количество системных CPU (2), поэтому наверняка возникнет большая конкуренция за CPU.
- Столбцы us (пользователь) и sy (система): общее использование CPU этими двумя столбцами возросло до 100%, а использование CPU системой (столбец sy) достигло 84%, что указывает на то, что CPU в основном занят ядром.
- в столбце
in
: количество прерываний также возросло примерно до 10 000, что указывает на то, что обработка прерываний также является потенциальной проблемой.
Рассматривая эти показатели вместе, мы можем сделать вывод, что очередь выполнения системы слишком длинная, то есть слишком много процессов запущено и ждет CPU. Это приводит к большому количеству переключений контекста, что в свою очередь приводит к более высокому использованию CPU системой.
Итак, какой именно процесс вызывает эти проблемы?
Давайте продолжим анализ, используя pidstat
в третьем терминале, чтобы посмотреть на ситуацию с переключением контекста CPU и процесса:
# вывод 1 набора данных каждую секунду (используйте Ctrl+C для остановки) # параметр `-w` указывает, что будут выводиться метрики переключения процессов, а параметр `-u` указывает, что будут выводиться метрики использования CPU $ pidstat -w -u 1 08:06:33 UID PID %usr %system %guest %wait %CPU CPU Command 08:06:34 0 10488 30.00 100.00 0.00 0.00 100.00 0 sysbench 08:06:34 0 26326 0.00 1.00 0.00 0.00 1.00 0 kworker/u4:2 08:06:33 UID PID cswch/s nvcswch/s Command 08:06:34 0 8 11.00 0.00 rcu_sched 08:06:34 0 16 1.00 0.00 ksoftirqd/1 08:06:34 0 471 1.00 0.00 hv_balloon 08:06:34 0 1230 1.00 0.00 iscsid 08:06:34 0 4089 1.00 0.00 kworker/1:5 08:06:34 0 4333 1.00 0.00 kworker/0:3 08:06:34 0 10499 1.00 224.00 pidstat 08:06:34 0 26326 236.00 0.00 kworker/u4:2 08:06:34 1000 26784 223.00 0.00 sshd
Из выходных данных pidstat
можно видеть, что увеличение загрузки CPU действительно вызвано sysbench
, нагрузка на CPU которым достигла 100%. Однако, переключения контекста происходят и из других процессов, с самой высокой частотой непроизвольного переключения контекста от pidstat
, а самая высокая частота произвольного переключения контекста — от потока ядра kworker
и sshd
.
Количество переключений контекста, о котором сообщает, pidstat
составляет всего несколько сотен, что значительно меньше 1,39 миллиона, о котором сообщает vmstat
. Что происходит? Может ли это быть проблемой самого инструмента?
Прежде чем делать выводы об инструменте, давайте вспомним различные сценарии переключения контекста, обсуждавшиеся ранее. Один важный момент, упомянутый здесь, заключается в том, что базовой единицей планирования в Linux на самом деле является поток, и в нашем сценарии sysbench
это имитация проблем планирования потока. Так может ли pidstat
игнорировать данные потока?
Запустив man pidstat
, вы обнаружите, что в pidstat
по умолчанию отображаются метрики для процессов. Однако, когда вы добавляете параметр -t
, он также будет отображать метрики для потоков.
Поэтому мы можем остановить предыдущий pidstat
в третьем терминале с помощью Ctrl+C
, добавить параметр -t
и попробовать снова, чтобы посмотреть, что произойдет:
# вывод 1 набора данных каждую секунду (используйте Ctrl+C для остановки) # параметр `-wt` указывает, что будут выведены метрики переключения контекста для потоков $ pidstat -wt 1 08:14:05 UID TGID TID cswch/s nvcswch/s Command ... 08:14:05 0 10551 - 6.00 0.00 sysbench 08:14:05 0 - 10551 6.00 0.00 |__sysbench 08:14:05 0 - 10552 18911.00 103740.00 |__sysbench 08:14:05 0 - 10553 18915.00 100955.00 |__sysbench 08:14:05 0 - 10554 18827.00 103954.00 |__sysbench ...
Теперь можно видеть, что хотя количество переключений контекста для процесса sysbench
(который является основным потоком) не выглядит очень высоким, количество переключений контекста для его дочерних потоков довольно существенно. Похоже, что виновником чрезмерного количества переключений контекста являются многочисленные потоки sysbench
.
Мы выявили основную причину увеличения количества переключений контекста, но заканчивается ли это расследование?
Конечно, нет. Вспомним, что ранее при наблюдении за системными метриками, помимо резкого увеличения частоты переключения контекста, другая метрика также показала существенное изменение. Да, количество прерываний. Количество прерываний также выросло до 10 000, но мы до сих пор не знаем, какой тип прерываний увеличился. Далее нам нужно продолжить наше расследование, чтобы найти источник.
Поскольку мы имеем дело с прерываниями, мы знаем, что они происходят только в режиме ядра. pidstat
— это всего лишь инструмент анализа производительности процесса, который не предоставляет никакой подробной информации о прерываниях. Как мы можем определить тип происходящих прерываний?
Путем чтения из файла /proc/interrupts
. /proc
— это виртуальная файловая система в Linux, используемая для связи между пространством ядра и пространством пользователя. /proc/interrupts
является частью этого механизма связи, предоставляя доступное только для чтения представление об использовании прерываний.
В третьем терминале остановим предыдущий pidstat
с помощью Ctrl+C
, а затем выполним следующую команду, чтобы наблюдать изменения в прерываниях:
# параметр `-d` указывает, что изменения в указанной области будут выделены $ watch -d cat /proc/interrupts CPU0 CPU1 ... RES: 2450431 5279697 Rescheduling interrupts ...
Понаблюдав некоторое время, можно заметить, что наиболее быстро меняющееся прерывание — это прерывание перепланирования (RES). Этот тип прерывания указывает на пробуждение простаивающего CPU для планирования новой задачи для выполнения. В многопроцессорной системе (SMP) планировщик использует этот механизм для распределения задач по разным CPU, обычно называемых межпроцессорными прерываниями (IPI).
Таким образом, увеличение количества прерываний по-прежнему обусловлено проблемой чрезмерного планирования задач, что согласуется с предыдущим анализом количества переключений контекста.
Этот случай демонстрирует преимущества использования нескольких инструментов и сравнения различных метрик. Если бы мы использовали их только в pidstat
, мы бы не обнаружили эти серьезные потоки переключения контекста.
Теперь вернемся к первоначальному вопросу: какое количество переключений контекста в секунду считается нормальным?
Ответ зависит от производительности CPU самой системы. Если количество переключений контекста относительно стабильно, то нормальным следует считать от нескольких сотен до менее десяти тысяч. Однако, когда количество переключений контекста превышает десять тысяч или показывает рост на порядок величины, скорее всего, есть проблема с производительностью.
На этом этапе также необходимо более подробно проанализировать тип переключения контекста. Например:
- Увеличение числа произвольных переключений контекста указывает на то, что процессы ждут ресурсов, возможно, из-за проблем с вводом-выводом или других проблем.
- Увеличение числа непроизвольных переключений контекста указывает на то, что процессы планируются принудительно, то есть они конкурируют за процессор, что позволяет предположить, что процессор стал узким местом.
- Увеличение количества прерываний указывает на то, что CPU занят процедурами обработки прерываний, и вам необходимо проанализировать конкретные типы прерываний, изучив файл
/proc/interrupts
.
На этом все! Спасибо за внимание! Если статья была интересна, подпишитесь на телеграм-канал usr_bin, где будет еще больше полезной информации.