Приоритет ввода вывода windows

Обновлено: 06.07.2024

В современных полновесных реализациях Windows (Windows 2000, Windows XP, Windows 2003) планировщик ядра выделяет процессорное время потокам. Управление волокнами возложено на приложения пользователя: Windows предоставляет набор функций, с помощью которых приложение может управлять созданными волокнами. Фактически для волокон реализуется невытесняющая многозадачность средствами приложения; с точки зрения операционной системы, все волокна должны быть созданы в рамках потоков (один поток может быть "расщеплен" на множество волокон средствами приложения) и система никак не вмешивается в их планирование.

В Windows определен список событий , которые приводят к перепланированию потоков:

  • создание и завершение потока;
  • выделенный потоку квант исчерпан;
  • поток вышел из состояния ожидания;
  • поток перешел в состояние ожидания;
  • изменен приоритет потока;
  • изменена привязка к процессору.

В целях уменьшения затрат на планирование потоков несколько изменен граф состояний потока. На рис. 6.6 приведен "классический" вид графа состояний задачи, а на рис. 6.8 - граф состояний потока в Windows. Переход из состояния "готовность" в состояние "выполнение" сделан в два этапа - выбранный к выполнению поток подготавливается к выполнению и переводится в состояние "выбран"; эта подготовка может осуществляться до наступления момента перепланирования, и в нужный момент достаточно просто переключить контекст выполняющегося потока на выбранный.

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

При выборе потока для выполнения учитываются приоритеты потоков (абсолютные приоритеты) - система начинает выполнять код потока с наибольшим приоритетом из числа готовых к исполнению.

Процесс выбора потока для выполнения усложняется в случае SMP систем, когда помимо приоритета готового к исполнению потока учитывается, на каком процессоре ранее выполнялся код данного потока.

В Windows выделяют понятие "идеального" процессора - им назначается процессор, на котором запускается приложение в первый раз. В дальнейшем система старается выполнять код потока именно на этом процессоре - для SMP систем это решение улучшает использование кэш-памяти, а для NUMA систем позволяет, по большей части, ограничиться использованием оперативной памяти, локальной для данного процессора. Заметим, что диспетчер памяти Windows при выделении памяти для запускаемого процесса старается учитывать доступность памяти для назначенного процессора в случае NUMA системы.

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

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

Управление квантованием

Квантование потоков осуществляется по тикам системного таймера , продолжительность одного тика составляет обычно 10 или 15 мс, больший по продолжительности тик назначают многопроцессорным машинам. Каждый тик системного таймера соответствует 3 условным единицам; величина кванта может варьироваться от 2 до 12 тиков (от 6 до 36 единиц).

Параметр реестра HKLM\SYSTEM\CurrentControlSet\Control\PriorityControl\ Win32PrioritySeparation предназначен для управления квантованием . На рис. 6.9 дан формат этого параметра для Windows 2000-2003, а в таблице 6.1 приводятся длительности квантов в условных единицах для разных значений полей параметра Win32PrioritySeparation.


Рис. 6.9. Управление квантованием в Windows (длительность кванта показана в табл. 6.1)

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

"System Properties|Advanced|Performance:Settings|Advanced|Adjust for best performance of:" позволяет выбрать только:

Короткие кванты переменной длины, значение 0x26 т.е. 10 01 10 (короткие кванты переменной длительности, 18 ед.).

Длинные кванты фиксированной длины, значение 0x18 т.е. 01 10 00 (длинные кванты фиксированной длительности, 36 ед.). Более тонкая настройка возможна с помощью редактора реестра.

Управление длительностью кванта связано с активностью процесса , которая определяется наличием интерфейса пользователя (GUI или консоль) и его активностью. Если процесс находится в фоновом режиме, то длительность назначенного ему кванта соответствует "нулевым" колонкам таблицы 6.1 (выделены серым цветом; т.е. длительности 6 или 12 - для переменной длины кванта или 18 и 36 - для фиксированной). Когда процесс становится активным, то ему назначается продолжительность квантов, исходя из значения двух младших бит параметра Win32PrioritySeparation в соответствии с приведенной таблицей.

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

Управление приоритетами

В Windows выделяется 32 уровня приоритетов. 0 соответствует самому низкому приоритету (с таким приоритетом работает только специальный поток обнуления страниц), 31 - самому высокому. Этот диапазон делится на три части:

Для некоторого упрощения управления приоритетами в Windows выделяют "классы приоритета" (priority class), которые задают базовый уровень приоритета, и "относительные приоритеты" потоков, которые корректируют указанный базовый уровень. Операционная система предоставляет набор функций для управления классами и относительными приоритетами потоков.

Планировщик операционной системы также может корректировать уровень приоритета (из диапазона 1-15), однако базовый уровень (т.е. класс) не может быть изменен. Такая коррекция приоритета выполняется в случае:

  • Завершения операции ввода-вывода - в зависимости от устройства, приоритет повышается на 1 - 8 уровней.
  • По окончании ожидания события или семафора (см. далее) - на один уровень.
  • При пробуждении GUI потоков - на 2 уровня.
  • По окончании ожидания потоком активного процесса (определяется по активности интерфейса ) - на величину, указанную младшими 2 битами параметра Win32PrioritySeparation (см. управление длительностью кванта).

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

Еще один случай повышения приоритета (вместе с увеличением длительности кванта) - процесс долгое время не получал процессорного времени. В этой ситуации система раз в 3-4 секунды назначает процессу приоритет, равный 15, и квант удвоенной длительности. По истечении этого кванта приоритет возвращается к прежнему значению и восстанавливается рекомендуемая длительность кванта.

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

Уровни приоритета с 16 по 31 отведены только для класса REALTIME_PRIORITY_CLASS

В зависимости от настройки планировщика, NORMAL_PRIORITY_CLASS с базовым уровнем приоритета 8 может быть "расщеплен" на два базовых уровня - для потоков активных процессов (базовый уровень 9) и для потоков фоновых процессов (базовый уровень 7). Для класса HIGH_PRIORITY_CLASS относительные приоритеты потока THREAD_PRIORITY_HIGHEST и THREAD_PRIORITY_TIME_CRITICAL дают одинаковое значение приоритета 15.

Этот раздел содержит параметры, используемые для ввода-вывода.

Windows XP и более поздних версий: Этот параметр задает длительность времени (в миллисекундах), в течение которого ядро СУБД будет обращаться к файлу, заблокированному до сбоя JET_errFileAccessDenied. Эта временная задержка предназначена для работы с антивирусным программным обеспечением, которое может содержать некоторые файлы ядра СУБД, открытые после их закрытия.

Примечание . В результате выполнения описанной выше логики повторных попыток присоединения к базе данных или использования файла журнала, который уже используется ядром СУБД, произойдет задержка этого размера, прежде чем вызов API вернет несанкционированный сбой. Этот параметр можно использовать для отключения задержки в случае, если это распространенный сценарий.

Значение по умолчанию:

Влияет на физический макет:

Влияет на надежность:

Влияет на производительность:

Влияет на ресурсы:

Windows XP и более поздних версий.

Если этот параметр имеет значение true, любая папка, отсутствующая в пути файловой системы, используемой ядром СУБД, будет создана автоматически. В противном случае операция, использующая отсутствующий путь файловой системы, завершится с JET_errInvalidPath.

Значение по умолчанию:

Влияет на физический макет:

Влияет на надежность:

Влияет на производительность:

Влияет на ресурсы:

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

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

Рассмотрим, как в системе Windows осуществляется планирование потоков для их выполнения на центральном процессоре. Также посмотрим на приоритеты процессов и потоков.

Планирование потоков в системе

В Windows всегда выполняется хотя бы один поток с самым высоким приоритетом. Если в системе много ядер, то Windows делит все ядра на группы по 64 ядра. Каждому процессу даётся доступ к определённой группе ядер. Следовательно потоки этих процессов могут видеть только свою группу ядер.

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

Поток может не отработать весь свой квант, так как если другой поток готов к выполнению и имеет более высокий приоритет, то он вытеснит первый поток.

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

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

Планирование осуществляется на уровне потоков, а не процессов. Например, Процесс_А имеет 10 потоков, а Процесс_Б – 2 потока. Тогда процессорное время распределился между этими 12 потоками равномерно.

Приоритеты потоков

Планирование потоков полагается на их приоритеты. Windows использует 32 уровня приоритета для потоков от 0 до 31:

  • 16 — 31 — уровни реального времени;
  • 1 — 15 — обычные динамические приоритеты;
  • 0 — зарезервирован для потока обнуления страниц.

Вначале поток получает свой Базовый приоритет, который наследуется от приоритета процесса:

Дальше назначается относительный приоритет который увеличивает или уменьшает приоритет потока:

После получения базового приоритета и корректировки относительным приоритетом получается динамический приоритет:

Изменить базовый приоритет процесса можно из “Диспетчера задач” на вкладке “Подробности“, или в “Process Explorer“. Однако, это не поменяет относительный приоритет потока.

Диспетчер задач. Проверка приоритета процесса, запущенного командой «start /low notepad.exe»

Приоритеты отдельных потоков можно посмотреть в программе “Process Explorer“. Но изменять их нет смысла, так как только разработчик данной программы понимает как лучше расставить приоритеты потокам.


Получается что относительный приоритет у потока Notepad.exe равен 2, так как динамический приоритет больше базового на 2.

Состояния потоков

Поток может находиться в следующих состояниях:

  • Готов (Ready) — поток готов к выполнению и ожидает процессор.
  • Готов с отложенным выполнением (Deferred ready) — поток выбран для выполнения на конкретном ядре и ожидает именно это ядро.
  • В повышенной готовности (Standby) — поток выбран следующим для выполнения на конкретном ядре. Как только сможет процессор выполнит переключение контекста на этот поток.
  • Выполнение (Running) — выполняется на процессоре пока не истечет его квант времени, или пока его не вытеснит поток с большем приоритетом.
  • Ожидание (Waiting) — поток ждет каких-то ресурсов.
  • Переходное состояние (Transition) — готов к выполнению, но стек ядра выгружен из памяти, как только стек загрузится в память поток перейдет в состояние Готов.
  • Завершение (Terminated) — поток выполнил свою работу и завершился сам, или его завершили принудительно.
  • Инициализация (Initializated) — состояние при создании потока.

Кванты времени

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

Итак, теперь я вам покажу как переключить систему на работу с длинным или коротким квантом. Длительность кванта времени настраивается тут: “Свойства системы” / “Дополнительные параметры системы” / “Дополнительно” / “Быстродействие” / “Параметры” / “Дополнительно”:

На серверной системе можно выбрать “программ” если это сервер терминалов или просто настольный компьютер с установленной серверной системой.

На десктопной системе можно выбрать “служб” если вы запускаете какую-то длительную компиляцию или рендерите видео, а потом вернуть обратно в состояние “программ“.

Изменение приоритета планировщиком

Планировщик Windows периодически меняет текущий приоритет потоков. Делается это например для:

  • повышения приоритета, если поток слишком долго ожидает выполнение (предотвращает зависание программы);
  • повышения приоритета, если происходит ввод из пользовательского интерфейса (сокращение времени отклика);
  • повышения приоритета, после завершения операции ввода/вывода (чтобы потоки ждущие ввод/вывод быстрее выполнялись). При ждать могут:
    • диск, cd-rom, параллельный порт, видео — повышение на 1 пункт;
    • сеть, почтовый слот, именованный канал, последовательный порт — повышение на 2 пункта;
    • клавиатура или мышь — повышение на 6 пунктов;
    • звуковая карта — повышение на 8 пунктов.

    Эксперимент

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

    1. Запустите программу «Блокнот».
    2. Запустите «Системный монитор».
    3. Щелкните на кнопке панели инструментов «Добавить» (Add Counter).
    4. Выберите объект «Поток» (Thread), а затем выберите счетчик «Текущий приоритет» (Priority Current).
    5. В поле со списком введите «Notepad», а затем щелкните на кнопке «Поиск» (Search).
    6. Найдите строку «Notepad/0». Выберите ее, щелкните на кнопке «Добавить» (Add), а затем щелкните на кнопке «ОК».
    7. Как только вы щелкните мышкой по блокноту, то заметите в Системном мониторе, что приоритет у потока «Блокнот» поднялся до 12, если свернуть блокнот то приоритет вновь упадет до 10.

    Поток простоя — idle

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

    Групповое планирование

    Планирование потоков на базе потоков отлично работает, но не способно решить задачу равномерного распределения процессорного времени между несколькими пользователями на терминальном сервере. Потому в Windows Server 2012 появился механизм группового планирования.

    Термины группового планирования:

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

    Где же применяется групповое планирование? Например его использует механизм DFSS для справедливого распределения процессорного времени между сеансами на машине. Этот механизм включается по умолчанию при установке роли служб терминалов.

    Помимо DFSS групповое планирование применяется в объектах Jobs (Задания), так мы можем ограничить Задание по % потребления CPU, например задание будет потреблять не больше 20% процессорного времени.

    соответствующая информация, кажется, немного рассеянные по сравнению с обычным МС документации. Существует эта белая книга, которая обсуждает приоритет ввода/вывода в windows. У этого документа, похоже, есть бета-флаги, но я думаю, что это, вероятно, в основном довольно точно.

    две важные вещи, чтобы отметить:

    1. вы можете только уменьшить приоритет запросов ввода-вывода ниже нормы.
    2. водитель может проигнорировать любой такой запрос и обработать его как все равно нормально.

    полезными API для клиентских приложений являются SetFileInformationByHandle:

    похоже, что "реальный" способ установить приоритет ввода-вывода процесса использует NtSetInformationProcess С ProcessIoPriority информация-класса. К сожалению, этот API недокументирован, но вы можете увидеть его в действии, подключив отладчик к taskeng.exe и взлом ExeTask::GetYourPrioritiesStraight .

    Я считаю PROCESS_INFORMATION_CLASS значение ProcessIoPriority равно 33 (0x21), а значения приоритета следующие:

    значения выше-лучшее предположение, основанное на том, что я могу сказать от отладчика; задача планировщик, похоже, использует значение 1 для задач с приоритетом 7 и значение 2 для задач с приоритетом 5 (см. этот вопрос и эта статья MSDN дополнительные приоритеты планировщика задач). Зову SetPriorityClass С PROCESS_MODE_BACKGROUND_BEGIN использует значение 0.

    к сожалению, я не нашел публичного API, который можно использовать для этого, кроме SetPriorityClass метод в ответе @1800 информации, который устанавливает приоритет очень низким.

    Edit: у меня написана утилита, которая может использоваться для запроса или установки IO prority процесса,здесь.

    правильный способ сделать это-позвонить SetProcessPriorityClass С PROCESS_BACKGROUND_MODE_BEGIN для запуска фонового режима. Это вызывает очень низкий (фоновый) приоритет ввода-вывода и приоритет бездействующего процессора. Когда закончите, вызовите SetProcessPriorityClass снова, поставляя PROCESS_BACKGROUND_MODE_END. То же самое можно сделать на уровне потока через в разделе setthreadpriority и THREAD_BACKGROUND_MODE_BEGIN / END.

    Если вы хотите непосредственно установите приоритет ввода-вывода, независимо от приоритета ЦП, вы должны использовать собственные API NT. Я задокументировал это здесь, но не включал примеры кода, поскольку мы все знаем, что они разорваны дословно.

    API, который вы хотите, - это NT Native API NtSetInformationProcess. Используя этот API, вы можете изменить приоритет ввода-вывода. Этот API принимает переменную "class", сообщающую, какой тип информации о процессе вы хотите изменить, эта переменная класса должна быть набор для ProcessIoPriority. Затем вы можете установить приоритет ввода-вывода всего процесса таким образом.

    аналогично, приоритет ввода / вывода может быть получен через NtQueryInformationProcess.

    плохая новость заключается в том, что уровни приоритета немного ограничен. Критическое зарезервировано для системных операций подкачки. Это оставляет вас с нормальный и Очень Низкая (фоном). Низкие и высокие могут или не могут быть реализованы в более новых версиях Windows. Там похоже на частичную поддержку, по крайней мере.

    Если у вас нет опыта работы с NT Native APIs, первое, что нужно сделать, это понять их. Как только вы это сделаете, вы увидите, что это так же просто, как один вызов API.

    Я пробовал выше установить приоритет процесса в приложении WPF, и он работает нормально. Не нужно устанавливать приоритет потока.

    EDIT: это выше относится к приоритету ЦП процесса, в отличие от приоритета ввода-вывода, однако может быть некоторая корреляция/связь между приоритетом ЦП процесса и его приоритетом ввода-вывода.

    обязательно выровняйте FILE_IO_PRIORITY_HINT_INFO структура правильно при вызове SetFileInformationByHandle .

    Читайте также: