CPU steal time - это время, в течение которого виртуальная машина не получает
ресурсы процессора для своего выполнения. Это время считается только в гостевых
операционных системах в средах виртуализации.
Что такое steal
Steal - это метрика, указывающая на нехватку процессорного времени для
процессов внутри виртуальной машины. Как описано в патче ядра KVM, steal -
это время, в течение которого гипервизор выполняет другие процессы на хостовой
операционной системе, хотя он поставил процесс виртуальной машины в очередь на
выполнение. То есть steal считается как разница между временем, когда процесс
готов выполниться, и временем, когда процессу выделено процессорное время.
Метрику steal ядро виртуальной машины получает от гипервизора. При этом
гипервизор не уточняет, какие именно другие процессы он выполняет, просто
"пока занят, тебе времени уделить не могу". На KVM поддержка подсчёта
steal добавлена в патчах. Ключевых моментов здесь два:
1. Виртуальная машина узнает о steal от гипервизора. То есть, с точки зрения
потерь, для процессов на самой виртуалке это непрямое измерение, которое может
быть подвержено различным искажениям.
2. Гипервизор не делится с виртуалкой информацией о том, чем он занят -
главное, что он не уделяет время ей. Из-за этого сама виртуалка не может
выявить искажения в показателе steal, которые можно было бы оценить по
характеру конкурирующих процессов.
Как вычислить steal
По сути, steal считается как обычное время утилизации процессора. В ядре
добавляется ещё один счетчик непосредственно для процесса KVM (процесса
виртуальной машины), который считает длительность пребывания процесса KVM в
состоянии ожидания процессорного времени. Счетчик берет информацию о процессоре
из его спецификации и смотрит, все ли его тики утилизированы процессом
виртуалки. Если все, то считаем, что процессор занимался только процессом
виртуальной машины. В ином случае информируем, что процессор занимался чем-то
еще, появился steal.
Подробнее читайте в статье Brendann Gregg.
Как мониторить steal
Мониторить steal внутри виртуальной машины можно как любую другую процессорную
метрику. Главное, чтобы виртуалка была на Linux. Windows такую информацию не предоставляет.
Сложность возникает при попытке получить эту информацию с гипервизора. Можно
попробовать спрогнозировать steal на хостовой машине, например, по параметру
Load Average (LA) - усредненного значения количества процессов, ожидающих в
очереди на выполнение. Методика подсчета этого параметра непростая, но в целом
пронормированный по количеству потоков процессора LA > 1 указывает на
перегрузку Linux-сервера.
Чего же ждут все эти процессы? Очевидный ответ - процессора. Но иногда
процессор свободен, а LA зашкаливает. На самом деле, процессы могут ожидать
окончания любой блокировки, как физической, связанной с устройством
ввода/вывода, так и логической, например мьютекса. Туда же относятся блокировки
на уровне железа (того же ответа от диска) или логики (так называемых
блокировочных примитивов).
Ещё одна особенность LA в том, что оно считается как среднее значение по ОС,
причём не меньше, чем за минуту. Например, 100 процессов конкурируют за один
файл, тогда LA=50. Такое большое значение, казалось бы, говорит, что ОС плохо.
Но для криво написанного кода это может быть нормой - плохо только ему, а
другие процессы не страдают. Из-за этого усреднения (причём не меньше, чем за
минуту), определение чего-либо по LA может закончиться весьма неопределенными
результатами в конкретных случаях.
Почему появляется steal и что делать
Остановимся на основных причинах появления steal, с которыми мы столкнулись при
работе с облачной платформой MCS, и способах борьбы с ними.
Переутилизация. Самое простое и частое - много запущенных виртуальных машин,
большое потребление процессора внутри них, большая конкуренция, утилизация по
LA больше 1 (в нормировке по процессорным тредам). Внутри всех виртуалок всё
тормозит. Steal, передаваемый с гипервизора, также растёт, надо
перераспределять нагрузку или кого-то выключать.
При этом нужно учитывать, что соотношение нагрузки на гипервизоре и steal
внутри виртуальной машины не всегда однозначно взаимосвязаны. Обе оценки steal
могут быть ошибочными в конкретных ситуациях при разных нагрузках.
Паравиртуализация против одиноких инстансов. На гипервизоре одна единственная
виртуалка, она потребляет небольшую его часть, но дает большую нагрузку по
вводу/выводу, например по диску. И откуда-то в ней появляется небольшой steal,
до 10%.
Тут дело как раз в блокировках на уровне паравиртуализированных драйверов.
Внутри виртуалки создается прерывание, оно обрабатывается драйвером и уходит в
гипервизор. Из-за обработки прерывания на гипервизоре для виртуалки это
выглядит как отправленный запрос, она готова к исполнению и ждёт процессора, но
процессорного времени ей не дают. Виртуалка думает, что это время украдено.
Это происходит в момент отправки буфера, он уходит в kernel space гипервизора,
и мы начинаем его ждать. Хотя, с точки зрения виртуалки, он должен сразу
вернуться. Следовательно, по алгоритму расчета steal это время считается
украденным. Скорее всего, в этой ситуации могут быть и другие механизмы
(например, обработка ещё каких-нибудь sys calls), но они не должны сильно отличаться.
Небольшой steal можно считать нормой (даже и без паравиртуализации, с учётом
нагрузки внутри виртуалки, особенностей нагрузки соседей, распределения
нагрузки по тредам и прочего). Однако важно обращать внимание на то, как себя
чувствуют приложения внутри виртуалок.
Шедулер против высоконагруженных виртуалок. Когда одна виртуалка страдает от
steal больше других, это связано с шедулером (распределением ресурсов между
процессами) - чем сильнее процесс нагружает процессор, тем скорее шедулер
его выгонит, чтобы остальные тоже могли поработать. Если виртуалка потребляет
немного, она почти не увидит steal: её процесс честно сидел и ждал, ему дадут
время. Если виртуалка дает максимальную нагрузку по всем своим ядрам, её чаще
выгоняют с процессора и не дают много времени. Шедулер плохо относится к
процессам, которые много просят. Большие виртуалки - зло.
Низкий LA, но есть steal. LA примерно 0,7 (то есть, гипервизор, кажется
недозагружен), но внутри отдельных виртуалок наблюдается steal:
1. Уже описанный выше вариант с паравиртуализацией. Виртуалка может получать
метрики, указывающие на steal, хотя у гипервизора всё хорошо. По результатам
наших экспериментов, такой вариант steal не превышает 10 % и не должен
оказывать существенного влияния на производительность приложений внутри виртуалки.
2. Неверно считается LA. Точнее, в каждый конкретный момент он считается
верно, но при усреднении получается заниженным. Например, если одна виртуалка
на треть гипервизора потребляет все свои процессоры ровно полминуты, LA за
минуту на гипервизоре будет 0,15; четыре такие виртуалки, работающие
одновременно, дадут 0,6. А то, что полминуты на каждой из них был steal под 25
% по LA, уже не вытащить.
3. Из-за шедулера, решившего, что кто-то слишком много ест, и пусть он
подождет, пока я займусь другими важными системными вещами. В итоге одни
виртуалки не видят никаких проблем, а другие испытывают серьезную деградацию производительности.
Другие искажения
Есть другие причины для искажений честной отдачи процессорного времени на
виртуалке. Например, сложности в расчёты вносят гипертрединг и NUMA. Они
запутывают выбор ядра для исполнения процесса, потому что шедулер использует
коэффициенты - веса, которые при переключении контекста выполняют
усложнённый подсчёт.
Бывают искажения из-за технологий типа турбобуста или, наоборот, режима
энергосбережения, которые при подсчёте утилизации могут искусственно повышать
или понижать частоту или даже квант времени на сервере. Включение турбобуста
уменьшает производительность одного процессорного треда из-за увеличения
производительности другого. В этот момент информация об актуальной частоте
процессора виртуальной машине не передается, и она считает, что её время кто-то
тырит (например, она запрашивала 2 ГГц, а получила вдвое меньше).
В общем, причин искажений может быть много. Чтобы выяснить steal в конкретной
системе, исследуйте различные варианты, собирайте метрики, тщательно их
анализируйте и продумывайте, как равномерно распределять нагрузку. От любых
кейсов возможны отклонения, которые надо подтверждать экспериментально или
смотреть в отладчике ядра. Начать лучше с книг, на которые я дал линки выше, и
съёма статистики с гипервизора утилитами типа perf, sysdig, systemtap, коих десятки.
|