0

Запрос устройства на выделение процессорного времени это

В этой статье мы поговорим на такие темы, как: планирование процессов операционной системой, выделение ресурсов процессу, состояния процесса в ОС.

Понятие «вычислительный процесс» (или просто «процесс») является одним из основных при рассмотрении свойств ОС. Последовательный процесс (задача) – это выполнение отдельной программы с ее данными на последовательном процессоре (программа, находящаяся в решении).

  • Выполнение прикладных программ пользователей.
  • Выполнение утилит и других системных обрабатывающих программ.
  • Трансляция исходной программы, ее исполнение.

Планирование процессов

В первых вычислительных системах любая программа могла выполняться только после полного выполнения предыдущей задачи. Такой режим работы получил название однозадачного(однопрограммного).

Поскольку первые вычислительные системы были построены в соответствии с принципами Джона Фон Неймана, все подсистемы и устройства компьютера управлялись исключительно центральным процессором. ЦП осуществлял и выполнение вычислений, и управление операциями ввода/вывода данных. Соответственно, пока осуществлялся обмен данными между оперативной памятью и внешними устройствами, процессор не мог выполнять вычисления.

Введение в состав вычислительной машины специальных контроллеров позволило совместить во времени (распараллелить) операции вывода полученных данных и последующие вычисления на ЦП. Однако все равно процессор продолжал часто и долго простаивать, дожидаясь очередной операции ввода/вывода. Поэтому было предложено организовать, так называемый, мультипрограммный (мультизадачный, многозадачный) режим работы вычислительной системы. Суть его заключается в том, что пока одна программа (один процесс или задача) ожидает завершения очередной операции ввода/вывода, другая программа (другая задача) может быть поставлена на решение.

Многозадачный режим можно охарактеризовать следующим образом:

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

Выделение ресурсов

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

При необходимости использовать какой–нибудь ресурс (оперативную память, устройства ввода/вывода, массив данных и др.) задача обращается к супервизору ОС (ее центральному управляющему модулю), посредством специальных вызовов (команд, директив) и сообщает о своем требовании. При этом указывается вид ресурса и, если надо, его объем (например, количество адресуемых ячеек ОП, количество дорожек или секторов на системном диске, устройство печати и объем выводимых данных).

Супервизор ОС может состоять из нескольких модулей: супервизора ввода/вывода, супервизора прерываний, супервизора программ, диспетчер задач и т.д.

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

  • он свободен и в системе нет запросов от задач более высокого приоритета к этому же ресурсу.
  • текущий запрос и ранее выданные запросы допускают совместное использование ресурса.
  • ресурс используется задачей низшего приоритета и может быть временно отобран (разделяемый ресурс).

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

После окончания работы с ресурсом задача опять с помощью специального вызова супервизора (посредством соответствующей директивы) сообщает ОС об отказе от ресурса, или ОС забирает ресурс сама, если управление возвращается супервизору после выполнения какой-либо системной функции. Супервизор ОС, получив управление по этому обращению, освобождает ресурс и проверяет, имеется ли очередь к освободившемуся ресурсу. Если очередь есть – в зависимости от принятой дисциплины обслуживания (правила обслуживания) и приоритетов заявок он выводит из состояния ожидания задачу, ждущую ресурс, и переводит ее в состояние готовности к выполнению. После этого управление либо передается данной задаче, либо возвращается той, которая только что освободила ресурс.

При выдаче запроса на ресурс задача может указать, хочет ли она владеть ресурсом монопольно или допускает совместное использование с другими задачами.

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

В однопрограммной ОС присутствует только один пользовательский процесс. В мультипрограммной системе на ресурсы могут претендовать много независимых процессов.

Планирование процессов – это управление распределением ресурсов процессора между различными конкурирующими процессами путем передачи им управления согласно некоторой стратегии планирования.

Состояние процесса

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

Если обобщать и рассматривать не только обычные ОС общего назначения, но и, например ОС реального времени, то можно сказать, что процесс может находиться в активном и пассивномсостоянии.

В активном состоянии (то есть во время своего существования) процесс может участвовать в конкуренции за использование ресурсов в ОС, а в – пассивном – он только известен системе, но в конкуренции не участвует (хотя его существование в системе сопряжено с предоставлением ему оперативной и/или внешней памяти).

В свою очередь активный процесс может быть в одном из следующих состояний:

  • Выполнения (running) – все затребованные процессом ресурсы выделены. В этом состоянии в каждый момент времени может находиться только один процесс, если речь идет об однопроцессорной вычислительной системе (процесс использует процессор для выполнения своих команд). В многопроцессорных системах при наличии соответствующей ОС количество активных процессов может достигать числа процессоров.
  • Готовности к выполнению (ready) – ресурсы могут быть предоставлены, тогда процесс перейдет в состояние выполнения (процессы не блокированы и не активны).
  • Блокирования или ожидания (blocked) – затребованные ресурсы не могут быть предоставлены, или операция ввода/вывода не завершена (выполнение процесса может быть продолжено только после наступления некоторого ожидаемого им события).

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

В любой момент времени выполняющимся процессом (т.е. использующим процессор) может быть только один процесс. При передаче управления процессу пользователя ОС устанавливает интервальный таймер. Тем самым задается квант времени, являющийся максимальным количеством времени процессора, на которое процесс получает управление. Если это время истекает, процесс переводится из состояния выполнения в состояние готовности. После этого ОС, согласно стратегии планирования, выбирает следующий процесс, находящийся в готовности, переводит его в состояние выполнения и передает ему управление.

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

В обычных ОС (на рассматривая ОС реального времени) процесс появляется при запуске какой-нибудь программы. ОС организует (выделяет) для нового процесса соответствующий дескрипторпроцесса и процесс начинает выполняться. Поэтому пассивного состояния не существует.

В ОС реального времени ситуация иная. Обычно при проектировании системы реального времени уже заранее бывает известен состав программ (задач), которые должны будут выполняться. Известны и многие их параметры, которые необходимо учитывать при распределении ресурсов (объем памяти, приоритет, средняя длительность выполнения, открываемые файлы, используемые устройства и т.п.). Поэтому для них заранее заводят дескрипторы задач, с тем, чтобы в последствии не тратить драгоценное время на организацию дескриптора и поиск для него необходимых ресурсов. Таким образом, в ОС реального времени многие процессы (задачи) могут находиться в состоянии бездействия – пассивном состоянии.

Переходы между состояниями процесса

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

  • обращениями к ОС с запросами ресурсов.
  • обращениями к ОС с запросами на выполнение системных функций.
  • взаимодействием с другими процессами.
  • появлением сигналов прерывания таймера.
  • появлением сигналов прерывания устройств ввода/вывода и др.

Возможные переходы процесса из одного состояния в другое отображены в виде схем состояний. Процесс из состояния бездействия может перейти в состояние готовности в следующих случаях:

  1. По команде оператора (пользователя). Имеет место в тех диалоговых ОС, где программа может иметь статус задачи (и при этом являться пассивной), а не просто быть исполняемым файлом и только на время исполнения получать статус задачи (как это происходит в большинстве современных ОС).
  2. При выборе из очереди планировщика (характерно для ОС, работающих в пакетном режиме).
  3. По вызову из другой задачи (посредством обращения к супервизору один процесс может создать, инициировать, приостановить, остановить, уничтожить другой процесс).
  4. По прерыванию от внешнего инициативного устройства (сигнал о свершении некоторого события может запускать соответствующую задачу).

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

  • При наступлении запланированного времени запуска программы.
Читайте также:  Как в яндекс навигаторе включить ночной режим

Из состояния выполнения процесс может выйти по одной из следующих причин:

  1. Процесс завершается, при этом он посредством обращения к супервизору передает управление ОС и сообщает о своем завершении. В результате этих действий супервизор либо переводит его в список бездействующих процессов (процесс переходит в пассивное состояние), либо уничтожает (уничтожается не сама программа, а именно задача, которая соответствовала выполнению некоторой программы). В состояние бездействия процесс может быть переведен принудительно: по команде оператора или путем обращения к супервизору ОС из другой задачи с требованием остановить данный процесс.
  2. Процесс переводится супервизором ОС в состояние готовности к исполнению в связи с появлением более приоритетной задачи или в связи с окончанием выделенного ему кванта времени.
  3. Процесс блокируется (переводится в состояние ожидания) либо вследствие запроса операции ввода/вывода либо в силу невозможности предоставить ему ресурс, запрошенный в настоящий момент, а также по команде оператора на приостановку задачи, или по требованию через супервизор другой задачи.

Таким образом, движущей силой, меняющей состояние процессов, являются различные события. Один из основных видов событий — это прерывание.

Какой бы ни была операционная система, перед ней стоит целый комплекс задач. И нам понадобится не раз возвращаться к этой теме, чтобы рассмотреть их все хотя бы в самых общих чертах. Темой нашего сегодняшнего повествования станет распределение операционной системой времени центрального процессора между различными задачами. Сегодня мы получим ответ на вопрос, который рано или поздно возникает у каждого любознательного пользователя: как операционная система распределяет время процессора для решения нескольких задач одновременно? Ведь под красочными обоями рабочего стола таится неутомимая труженица, способная день и ночь решать поставленные перед ней пользователем задачи. За ее плечами нелегкий груз забот, но обычно она несет его с легкостью, кроме некоторых ситуаций, когда пользователь требует от своей помощницы невозможного.


Все выполняемые операционной системой задачи можно сгруппировать по шести категориям:

  1. Управление процессором (Processor management)
  2. Управление памятью (Memory management)
  3. Управление устройством (Device management)
  4. Управление накопителем (Storage management)
  5. Интерфейс приложения (Application interface)
  6. Интерфейс пользователя (User interface)

Читатели могут отметить, что современная операционная система умеет много такого, что не вмещается ни в одну из этих шести групп. И будут правы. Разработчики операционных систем оснащают их множеством вспомогательных утилит и дополнительных функций. Но эти шесть категорий, которые нам предстоит рассмотреть, составляют саму суть того, что положено делать операционной системе.

Управление процессором


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

  • Обеспечение каждого программного процесса и приложения достаточным для корректного функционирования временем процессора
  • Использование циклов процессора в том объеме, который реально необходим для работы

Основной единицей программного обеспечения, которой операционная система выделяет процессорное время, является процесс или поток (тред). Это зависит от конкретной операционной системы.

Можно даже сказать, что операционная система склонна воспринимать процесс в качестве приложения. Но это упрощение не описывает всей сложности взаимодействия процессов с операционной системой и аппаратным обеспечением компьютера. Процессом является любое приложение: текстовый редактор, электронная таблица или игра. Но приложение может вести к запуску дополнительных процессов, обеспечивающих взаимодействие с устройствами или другими компьютерами.

Когда операционная система работает, в ней запущено множество процессов, которые даже не дают вам знать о своем существовании. Например, в Windows XP или UNIX работают десятки фоновых процессов. В список их задач входят: обеспечение работы сети, управление памятью компьютера и его дисками, проверка системы на вирусы. Разумеется, этим круг их задач не исчерпывается.

Процессом называется программное обеспечение, выполняющее некую работу. Каждый процесс должен кем-то или чем-то контролироваться: операционной системой, другим приложением или непосредственно пользователем.

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

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

Но некоторые прерывания крайне важны и не игнорируются. Речь идет о проблемах памяти и ошибках. Эти прерывания называют немаскируемыми и они обрабатываются немедленно, вне зависимости от того, над какими задачами в данный момент работает процессор. В качестве наиболее яркого (но, разумеется, не единственного) примера немаскируемого прерывания можно привести прерывание по прекращению подачи питания. Нетрудно понять, что такое прерывание всегда ведет к прекращению работы процессора по весьма уважительной причине.

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

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

  • Процесс занимает определенный объем в оперативной памяти (ОЗУ, RAM). Он также может использовать регистры, стеки и очереди в рамках памяти процессора и операционной системы
  • Когда два процесса выполняются одновременно в многозадачном режиме, операционная система выделяет одной программе определенное количество исполнительных циклов процессора
  • После выполнения этой последовательности циклов, операционная система копирует состояние всех регистров, стеков и очередей, использованных в ходе работы над выполнением процесса и отмечает точку, в которой выполнение процесса было приостановлено
  • Затем загружает все регистры, стеки и очереди, используемые вторым процессом и позволяет процессору уделить ему некоторое количество циклов
  • Когда все это уже произошло, она вновь копирует состояние всех регистров, стеков и очередей, использованных второй программой и в очередной раз загружает первую программу

Управляющий блок процесса


Вся информация, необходимая для отслеживания процесса, содержится в пакете данных, именуемом управляющим блоком процесса (process control block). Таким образом состояние процесса не теряется при переключении между задачами. В общем случае, управляющий блок процесса содержит:

  • Номер-идентификатор (ID), идентифицирующий данный процесс
  • Указатели и положения программы и ее данных на момент последней обработки процесса
  • Контент регистра
  • Состояния различных признаков и переключателей
  • Список открытых процессом файлов
  • Приоритет процесса
  • Статус всех необходимых данному процессу устройств ввода и вывода

Каждый процесс характеризуется связанным с ним статусом (состоянием). Многие процессы в определенных ситуациях не требуют времени центрального процессора. К примеру, процесс может находиться в состоянии ожидания нажатия пользователем клавиши. В этом состоянии процесс называют приостановленным (suspended). Когда поступает информация о нажатии клавиши, операционная система меняет его статус. В данном конкретном примере речь идет о том, что статус ожидания сменяется статусом исполнения. Для продолжения выполнения процесса используется информация из его управляющего блока.

Подкачка процессов не требует непосредственного вмешательства пользователя. Каждый процесс получает в свое распоряжение достаточно циклов процессора, чтобы выполнить свою задачу за разумный промежуток времени. Проблемы наступают, когда пользователь начинает одновременно работать со слишком большим числом процессов. Операционная система и сама требует определенного количества циклов процессора на сохранение всех регистров и очередей и переключение между задачами. Операционная система не идеальна, и может случиться так, что она начнет использовать большую часть отведенных ей циклов процессора на переключение между процессами, а не на их запуск. Это называется пробуксовкой и обычно требует вмешательства пользователя. Ему необходимо завершить некоторые процессы и навести порядок в работе системы.

Читайте также:  Вход в мой канал на яндекс дзен

Все рассмотренное нами выше касается тех случаев, когда компьютер располагает всего одним процессором. На машинах, располагающих двумя и более процессорами, операционной системе приходится распределять между ними свою рабочую нагрузку. И при этом стараться поддержать баланс между потребностями процессов и количеством доступных циклов разных процессоров. Асимметричные операционные системы выделяют один из процессоров под свои собственные нужды, а процессы приложений распределяют между остальными. Симметричные операционные системы распределяют свои нужды между несколькими процессорами даже в тех случаях, если никаких других задач больше не запущено.

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

Продолжение следует…

Привет! Хочу рассказать простым языком о механике возникновения steal внутри виртуальных машин и о некоторых неочевидных артефактах, которые нам удалось выяснить при его исследовании, в которое мне пришлось погрузиться как техдиру облачной платформы Mail.ru Cloud Solutions. Платформа работает на KVM.

CPU steal time — это время, в течение которого виртуальная машина не получает ресурсы процессора для своего выполнения. Это время считается только в гостевых операционных системах в средах виртуализации. Причины, куда деваются эти самые выделенные ресурсы, как и в жизни, весьма туманны. Но мы решили разобраться, даже поставили целый ряд экспериментов. Не то чтобы мы теперь всё знаем о steal, но кое-что интересное сейчас расскажем.

1. Что такое steal

Итак, steal — это метрика, указывающая на нехватку процессорного времени для процессов внутри виртуальной машины. Как описано в патче ядра KVM, steal — это время, в течение которого гипервизор выполняет другие процессы на хостовой ОС, хотя он поставил процесс виртуальной машины в очередь на выполнение. То есть, steal считается как разница между временем, когда процесс готов выполниться, и временем, когда процессу выделены процессорное время.

Метрику steal ядро виртуальной машины получает от гипервизора. При этом гипервизор не уточняет, какие именно другие процессы он выполняет, просто «пока занят, тебе времени уделить не могу». На KVM поддержка подсчёта steal добавлена в патчах. Ключевых моментов здесь два:

  • Виртуальная машина узнаёт о steal от гипервизора. То есть, с точки зрения потерь, для процессов на самой виртуалке это непрямое измерение, которое может быть подвержено различным искажениям.
  • Гипервизор не делится с виртуалкой информацией о том, чем другим он занят — главное, что он не уделяет время ей. Из-за этого сама виртуалка не может выявить искажения в показателе steal, которые можно было бы оценить по характеру конкурирующих процессов.

2. Что влияет на steal

2.1. Вычисление steal

По сути, steal считается примерно так же, как и обычное время утилизации процессора. Информации о том, как считается утилизация, не много. Наверное, потому что большинство считает этот вопрос очевидным. Но здесь тоже бывают подводные камни. Для ознакомления с этим процессом можно прочитать статью Brendann Gregg: вы узнаете о куче нюансов при расчете утилизации и о ситуациях, когда этот подсчёт будет ошибочным по следующим причинам:

  • Перегрев процессора, при котором пропускаются такты.
  • Включение/выключение турбобуста, в результате которого изменяется тактовая частота процессора.
  • Изменение продолжительности кванта времени, происходящее при использовании технологий энергосбережения процессора, например SpeedStep.
  • Проблема подсчёта среднего: оценка утилизации в течение одной минуты на уровне 80 % может спрятать кратковременный бурст в 100 %.
  • Циклическая блокировка (spin lock) приводит к тому, что процессор утилизирован, но пользовательский процесс не видит продвижения по своему выполнению. В результате расчётная утилизация процессора процессом будет стопроцентной, хотя физически процессорное время процесс потреблять не будет.

Статьи, описывающей подобный подсчёт для steal, я не нашел (если знаете — поделитесь в комментариях). Но, судя по исходникам, механизм расчёта такой же, как и для утилизации. Просто в ядре добавляется еще один счётчик, непосредственно для процесса KVM (процесса виртуальной машины), который считает длительность пребывания процесса KVM в состоянии ожидания процессорного времени. Счётчик берет информацию о процессоре из его спецификации и смотрит, все ли его тики утилизированы процессом виртуалки. Если все, то считаем, что процессор занимался только процессом виртуальной машины. В ином случае мы информируем, что процессор занимался чем-то ещё, появился steal.

Процесс подсчёта steal подвержен тем же самым проблемам, что и обычный подсчёт утилизации. Не сказать, что такие проблемы появляются часто, но выглядят обескураживающе.

2.2. Типы виртуализации на KVM

Вообще говоря, есть три типа виртуализации, и все они поддерживаются KVM. От типа виртуализации может зависеть механизм возникновения steal.

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

  1. Гостевая операционная система посылает своему гостевому устройству команду.
  2. Драйвер гостевого устройства принимает команду, формирует запрос для BIOS устройства и отправляет её в гипервизор.
  3. Процесс гипервизора производит трансляцию команды в команду для физического устройства, делая её, в том числе, более безопасной.
  4. Драйвер физического устройства принимает модифицированную команду и отправляет её уже в само физическое устройство.
  5. Результаты выполнения команд идут обратно по тому же пути.

Преимущество трансляции в том, что она позволяет эмулировать любое устройство и не требует специальной подготовки ядра операционной системы. Но за это приходится расплачиваться, прежде всего, быстродействием.

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

Паравиртуализация (paravirtualization). Самый распространённый вариант виртуализации устройств на KVM и вообще самый распространенный режим виртуализации для гостевых операционных систем. Особенность его в том, что работа с некоторыми подсистемами гипервизора (например, с сетевым или дисковым стеком) или выделение страниц памяти происходит с использованием API гипервизора, без трансляции низкоуровневых команд. Недостаток этого способа виртуализации — необходимость модификации ядра гостевой операционной системы, чтобы оно могло взаимодействовать с гипервизором с помощью этого API. Но обычно это решается за счет установки специальных драйверов на гостевую операционную систему. В KVM это API называется virtio API.

При паравиртуализации, по сравнению с трансляцией, путь до физического устройства значительно сокращается за счёт отправки команд напрямую из виртуальной машины в процесс гипервизора на хосте. Это позволяет ускорить выполнение всех инструкций внутри виртуальной машины. В KVM за это отвечает virtio API, который работает только для определенных устройств, вроде сетевого или дискового адаптера. Именно поэтому внутрь виртуальных машин ставятся virtio-драйверы.

Обратная сторона такого ускорения — не все процессы, которые выполняются внутри виртуалки, остаются внутри неё. Это создаёт некоторые спецэффекты, которые могут привести к появлению на steal. Подробное изучение этого вопроса рекомендую начать с An API for virtual I/O: virtio.

2.3. «Справедливый» шедулинг

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

В Linux используется так называемый CFS, Completely Fair Scheduler, начиная с ядра 2.6.23 ставший диспетчером по умолчанию. Чтобы разобраться с этим алгоритмом, можно почитать Linux Kernel Architecture или исходники. Суть CFS заключается в распределении процессорного времени между процессами в зависимости от длительности их выполнения. Чем больше процессорного времени требует процесс, тем меньше этого времени он получает. Это гарантирует «честное» выполнение всех процессов — чтобы один процесс не занимал все процессоры постоянно, и остальные процессы тоже могли выполняться.

Иногда такая парадигма приводит к интересным артефактам. Давние пользователи Linux наверняка помнят замирание обычного текстового редактора на десктопе во время запуска ресурсоемких приложений типа компилятора. Так получалось, потому что нересурсоемкие задачи десктопных приложений конкурировали с задачами, активно потребляющими ресурсы, такими как компилятор. CFS считает, что это нечестно, поэтому периодически останавливает текстовый редактор и даёт процессору обработать задачи компилятора. Это поправили с помощью механизма sched_autogroup, но остались многие другие особенности распределения процессорного времени между задачами. Собственно, это рассказ не про то, как всё плохо в CFS, а попытка обратить внимание на то, что «честное» распределение процессорного времени — не самая тривиальная задача.

Ещё один важный момент в шедулере — preemption. Это нужно, чтобы выгнать зажравшийся процесс с процессора и дать поработать другим. Процесс изгнания называется context switching, переключение контекста процессора. При этом сохраняется весь контекст таски: состояние стека, регистры и прочее, после чего процесс отправляется ждать, а на его место встает другой. Это дорогая операция для ОС, и используется она редко, но по сути ничего плохого в ней нет. Частое переключение контекста может говорить о проблеме в ОС, но обычно оно идет непрерывно и ни на что особенно не указывает.

Читайте также:  Защита блока питания от кз и перегрузок

Такой длинный рассказ нужен для объяснения одного факта: чем больше ресурсов процессора пытается потребить процесс в честном шедулере Linux, тем быстрее он будет остановлен, чтобы другие процессы тоже могли поработать. Правильно это или нет — сложный вопрос, который при разных нагрузках решается по-разному. В Windows до недавнего времени шедулер был ориентирован на приоритетную обработку десктопных приложений, из-за чего могли зависать фоновые процессы. В Sun Solaris было пять различных классов шедулеров. Когда запустили виртуализацию, добавили шестой, Fair share scheduler, потому что предыдущие пять работали с виртуализацией Solaris Zones неадекватно. Подробное изучение этого вопроса рекомендую начать с книг вроде Solaris Internals: Solaris 10 and OpenSolaris Kernel Architecture или Understanding the Linux Kernel.

2.4. Как мониторить steal?

Мониторить steal внутри виртуальной машины, как и любую другую процессорную метрику, просто: можно пользоваться любым средством съема метрик процессора. Главное, чтобы виртуалка была на Linux. Windows почему-то такую информацию своим пользователям не предоставляет. 🙁


Вывод команды top: детализация нагрузки на процессор, в крайней правой колонке — steal

Сложность возникает при попытке получить эту информацию с гипервизора. Можно попробовать спрогнозировать steal на хостовой машине, например, по параметру Load Average (LA) — усредненного значения количества процессов, ожидающих в очереди на выполнение. Методика подсчёта этого параметра непростая, но в целом, если пронормированный по количеству потоков процессора LA больше 1, это говорит о том, что сервер с линуксом чем-то перегружен.

Чего же ждут все эти процессы? Очевидный ответ — процессора. Но ответ не совсем правильный, потому что иногда процессор свободен, а LA зашкаливает. Вспомните, как отваливается NFS и как при этом растёт LA. Примерно так же может быть и с диском, и с другими устройством ввода/вывода. Но на самом деле, процессы могут ожидать окончания любой блокировки, как физической, связанной с устройством ввода/вывода, так и логической, например мьютекса. Туда же относятся блокировки на уровне железа (того же ответа от диска), или логики (так называемых блокировочных примитивов, куда входит куча сущностей, mutex adaptive и spin, semaphores, condition variables, rw locks, ipc locks. ).

Ещё одна особенность LA в том, что оно считается как среднее значение по операционной системе. К примеру, 100 процессов конкурируют за один файл, и тогда LA=50. Такое большое значение, казалось бы, говорит о том, что операционке плохо. Но для иного криво написанного кода это может быть нормальным состоянием, при том, что плохо только ему, а другие процессы в операционке не страдают.

Из-за этого усреднения (причём не меньше, чем за минуту), определение чего-то бы то ни было по показателю LA — не самое благодарное занятие, с весьма неопределёнными результатами в конкретных случаях. Если вы попытаетесь разобраться, то обнаружите, что в статьях на Википедии и прочих доступных ресурсах описаны только самые простые кейсы, без глубокого объяснения процесса. Всех интересующихся отправляю, опять же, сюда, к Brendann Gregg — далее по ссылкам. Кому лень на английском — перевод его популярной статьи про LA.

3. Спецэффекты

Теперь остановимся на основных кейсах появления steal, с которыми мы сталкивались. Расскажу, как они вытекают из всего вышесказанного и как соотносятся с показателями на гипервизоре.

Переутилизация. Самое простое и частое: гипервизор переутилизирован. Действительно, много запущенных виртуалок, большое потребление процессора внутри них, большая конкуренция, утилизация по LA больше 1 (в нормировке по процессорным тредам). Внутри всех виртуалок всё тормозит. Steal, передаваемый с гипервизора, также растёт, надо перераспределять нагрузку или кого-то выключать. В общем, всё логично и понятно.

Паравиртуализация против одиноких инстансов. На гипервизоре одна единственная виртуалка, она потребляет небольшую его часть, но даёт большую нагрузку по вводу/выводу, например по диску. И откуда-то в ней появляется небольшой steal, до 10 % (как показывают несколько проведённых экспериментов).

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

Это происходит в момент отправки буфера, он уходит в kernel space гипервизора, и мы начинаем его ждать. Хотя, с точки зрения виртуалки, он должен сразу вернуться. Следовательно, по алгоритму расчёта steal это время считается украденным. Скорее всего, в этой ситуации могут быть и другие механизмы (например, обработка ещё каких-нибудь sys calls), но они не должны сильно отличаться.

Шедулер против высоконагруженных виртуалок. Когда одна виртуалка страдает от steal больше других, это связано как раз с шедулером. Чем сильнее процесс нагружает процессор, тем скорее шедулер его выгонит, чтобы остальные тоже могли поработать. Если виртуалка потребляет немного, она почти не увидит steal: её процесс честно сидел и ждал, надо ему давать побольше времени. Если виртуалка производит максимальную нагрузку по всем своим ядрам, её чаще выгоняют с процессора и стараются не давать много времени.

Ещё хуже, когда процессы внутри виртуалки пытаются заполучить больше процессора, потому что не справляются с обработкой данных. Тогда операционная система на гипервизоре, за счёт честной оптимизации, будет давать всё меньше процессорного времени. Этот процесс происходит лавинообразно, и steal подскакивает до небес, хотя остальные виртуалки его могут почти не замечать. И чем больше ядер, тем хуже попавшей под раздачу машине. Короче говоря, больше всего страдают высоконагруженные виртуалки со множеством ядер.

Низкий LA, но есть steal. Если LA примерно 0,7 (то есть, гипервизор, кажется недозагружен), но внутри отдельных виртуалок наблюдается steal:

  • Уже описанный выше вариант с паравиртуализацией. Виртуалка может получать метрики, указывающие на steal, хотя у гипервизора всё хорошо. По результатам наших экспериментов, такой вариант steal не превышает 10 % и не должен оказывать существенного влияния на производительность приложений внутри виртуалки.
  • Неверно считается параметр LA. Точнее, в каждый конкретный момент он считается верно, но при усреднении за одну минуту получается заниженным. Например, если одна виртуалка на треть гипервизора потребляет все свои процессоры ровно полминуты, то LA за минуту на гипервизоре будет 0,15; четыре такие виртуалки, работающие одновременно, дадут 0,6. А то, что полминуты на каждой из них был дикий steal под 25 % по показателю LA, уже не вытащить.
  • Опять же, из-за шедулера, решившего, что кто-то слишком много ест, и пусть этот кто-то подождёт. А я пока попереключаю контекст, пообрабатываю прерывания и займусь другими важными системными вещами. В итоге одни виртуалки не видят никаких проблем, а другие испытывают серьезную деградацию производительности.

4. Другие искажения

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

Бывают искажения из-за технологий типа турбобуста или, наоборот, режима энергосбережения, которые при подсчёте утилизации могут искусственно повышать или понижать частоту или даже квант времени на сервере. Включение турбобуста уменьшает производительность одного процессорного треда из-за увеличения производительности другого. В этот момент информация об актуальной частоте процессора виртуальной машине не передаётся, и она считает, что её время кто-то тырит (например, она запрашивала 2 ГГц, а получила вдвое меньше).

В общем, причин искажений может быть много. В конкретной системе вы можете обнаружить что-то ещё. Начать лучше с книг, на которые я дал линки выше, и съема статистики с гипервизора утилитами типа perf, sysdig, systemtap, коих десятки.

admin

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *