Skip to content

Latest commit

 

History

History
246 lines (152 loc) · 22.3 KB

File metadata and controls

246 lines (152 loc) · 22.3 KB


🚥 Оптимизация задержек

Отключение таймера HPET

Основная проблема в Windows с которой нам нужно бороться – это использование таймера HPET [?], что уже создаёт лишнюю абстракцию, т.к. это является заменой стандартного таймера RTC [?] или того же HPET (реализаций много, это не так важно), который уже встроен во все современные материнские платы и является аппаратным. В этом и кроется проблема – Windows всё равно тянет одеяло на себя и использует свой программный таймер, так или иначе.

Изначально идея нового таймера здравая и хорошая – добиться более высокой точности для управления прерываниями [?] для мультимедийных программ, хотя у него и намного больше применений, в том числе он отвечает за счёт времени и многое другое. Но мы бы тут не собрались, если бы он работал так как задумывалось. Проблем таймер создаёт достаточно [Проблемы с HPET]. Если вкратце, то значение выдаваемое таймером должно быть строго фиксированным, но в виду своей странной реализации оно имеет плавающее значение и периодические меняется, из-за чего прерывания происходят в разное время, что и вызывает запоздания, а они в свою очередь микрофризы и микролаги, особенно это заметно при использовании игр или высоконагруженных приложений (рендер, обработка фотографий и т.п.).

Некоторые мультимедийные программы, а так же игры могут сами фиксировать данный параметр для увеличения плавности [?], поэтому мы его сами зафиксируем на минимально возможном значении в 0.5ms, для всей системы в том числе.

‼️ Ни в коем случае не отключайте данный таймер в BIOS – там он должен быть включён для корректной работы системы в целом. В новых версиях BIOS подобная настройка включена по-умолчанию и зачастую её изменение не возможно. Подробную информацию как изменить параметры в BIOS можно найти в руководстве к материнской плате или в интернете.

Для того чтобы отключить HPET в Windows необходимо использовать встроенную утилиту bcdedit. Но сперва нам надо убедиться, что таймер в Windows активен:

bcdedit /enum

Проверка активности таймера HPET с помощью BCDEdit

Если у вас нет значений useplatformtick и disabledynamictick или они установлены как No, то первым шагом для нас будет их отключение:

bcdedit /set disabledynamictick yes
bcdedit /set useplatformtick yes
Сброс значений по-умолчанию
bcdedit /set disabledynamictick no > nul
bcdedit /set useplatformtick no > nul

Пример правильного отключения таймера HPET в Windows:

Пример правильного отключения таймера HPET в Windows с помощью BCDEdit


Теперь, отключив таймер в Windows, нам надо зафиксировать его в значении 0.5ms – для этого необходимо использовать утилиту Intelligent Standby List Cleaner [скачать]. Здесь можно увидеть, что значение нашего таймера Current timer resolution постоянно изменяется, что не есть хорошо и именно это нам надо исправлять.

Пример не настроенного таймера в Intelligent Standby List Cleaner:

Пример не настроенного таймера в Intelligent Standby List Cleaner

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

  • Start ISCL minimized and auto-Start monitoring включено
  • Launch ISCL on user logon (TaskSheduler) включено
  • Enable custom timer resolution включено
  • Wanted timer resolution установлено в 0.50

Так же здесь можно настроить очищение системного кэша памяти [?]. Для этого необходимо изменить параметр Free memory is lower than, который отвечает за минимальное значение свободной памяти – оптимальным значением является размер вашей памяти разделённый на 2, после достижения которого кэш памяти будет очищен. Параметр The list size is at least отвечает за минимальный размер кэшированный памяти и его рекомендуется оставлять дефолтным - равным 1024 Mb.

Если лень считать
(4 Gb)  4096  /2 = 2048
(8 Gb)  8192  /2 = 4096
(16 Gb) 16384 /2 = 8192
(24 Gb) 24576 /2 = 12288
(32 Gb) 32768 /2 = 16384

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

После настройки надо нажать Start и проверить зафиксирован ли таймер – значение Current timer resolution должно быть строго равно 0.5ms и не изменяться. Значение может обновится с задержкой!

Пример правильной настройки Intelligent Standby List Cleaner:

Пример правильной настройки Intelligent Standby List Cleaner

Включение MSI mode

💡 Для дальнейшей настройки необходимо ознакомиться c Определение IRQ, Определение USB Host Controller.

А зачем нам ещё включать какой-то MSI mode [?]? Всё очень просто, если раньше на одно устройство выделялось всего 4 прерывания [Страдания по IRQ], то с помощью MSI стало возможным увеличить их до 32, что значительно ускоряет общение между устройствами.

Почти все последние драйверы, от нормальных производителей, используют изначально режим прерывания MSI, тем более это обязательное условие для PCI Express железок. Но для ускорения всей системы так же не лишним будет включение MSI и для USB Host Controller.

Для включения MSI mode мы будем использовать утилиту MSI Util v2 [скачать]. Ищем здесь нашу видеокарту и USB Host Controller (если по названию не получается найти, то в строке с именем так же указан Device ID). Ставим галочку в столбце MSI, так же меняем Interrupt priority на Hight, после чего жмём кнопку Apply.

Пример настройки MSI с помощью MSI Util v2:

Пример настройки MSI с помощью MSI Util v2

‼️ Нельзя устанавливать использование MSI mode для всех ваших устройств, иначе устройства могут работать не корректно.

⚠️ Данная настройка сбрасывается на дефолтное значение после обновления драйвера nVidia!

Приоритизация прерываний

💡 Для дальнейшей настройки необходимо ознакомиться c Работа с реестром, Определение IRQ.

Продолжая тему прерываний, далее нам необходимо настроить приоритет прерываний для конкретно заданных устройств – этим в Windows занимается IRQL [?]. Проблема приоритизации всегда имеет место быть, т.к. каждое устройство считает себя важней остальных и это порождает некоторые проблемы [Проблемы IRQL].

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\PriorityControl]
; видеокарта
"IRQ***Priority"=dword:00000001 ; none
; USB Host Controller
"IRQ***Priority"=dword:00000002 ; none
Значения по-умолчанию:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\PriorityControl]
"IRQ***Priority"=-
"IRQ***Priority"=-

В качестве имени параметра мы используем IRQ***Priority, где *** надо заменить на IRQ (несколько цифр) нашей видеокарты и USB Host Controller.

✨ Для видеокарты рекомендуется ставить значение равным 1, для USB Host Controller – значение 2 [Приоритеты IRQ].

Приоритизация драйверов

💡 Для дальнейшей настройки необходимо ознакомиться c Работа с реестром.

Следующим шагом после настройки приоритетов IRQL [?] необходимо указать приоритет для каких сервисов (в нашем случае драйверов) необходимо выполнять прерывания в первую очередь. Когда происходит прерывание, Windows, используя IRQL для определения приоритета прерывания, проверяет может ли прерывание обслуживаться в данный момент или нет, если условие выполняется, то приоритет потока начинает его выполнение. Всё что ниже по приоритету – ставиться в очередь. Таким образом мы зафиксируем критически важные сервисы, прерывания от которых необходимо обрабатывать в первую очередь.

Windows Registry Editor Version 5.00

; DirectX Graphics Kernel
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\DXGKrnl\Parameters]
"ThreadPriority"=dword:0000000f

; драйвер видеокарты nVidia
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\nvlddmkm\Parameters]
"ThreadPriority"=dword:0000001f

; USB3 HUB Driver
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\USBHUB3\Parameters]
"ThreadPriority"=dword:0000000f

; USB xHCI Compliant Host Controller
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\USBXHCI\Parameters]
"ThreadPriority"=dword:0000000f
Значения по-умолчанию:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\DXGKrnl\Parameters]
"ThreadPriority"=-

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\nvlddmkm\Parameters]
"ThreadPriority"=-

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\USBHUB3\Parameters]
"ThreadPriority"=-

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\USBXHCI\Parameters]
"ThreadPriority"=-

✨ В качестве параметра установите значения равным 15 (f) (что соответствует Hight), если система работает стабильно, то можно повысить приоритет установив параметр равным 31 (1f) (что соответствует Realtime) [Процессы и потоки в Windows] для nvlddmkm.

Распараллеливание драйверов по ядрам

💡 Для дальнейшей настройки необходимо ознакомиться c Определение IRQ, Определение USB Host Controller.

Самое сложное осталось позади и теперь мы будет освобождать первое ядро, куда Windows зачем-то добавляет почти все драйверы. Этим мы с одной стороны разгрузим ядро, а с другой так же уменьшим задержки.

Для этого нам понадобиться утилита Interrupt Affinity Policy Tool [скачать].

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

Сообщение об ошибке в утилите Interrupt Affinity Policy Tool

Пример списка устройств в утилите Interrupt Affinity Policy Tool:

Пример списка устройств в утилите Interrupt Affinity Policy Tool

В этом списке надо найти свою видеокарту и USB Host Controller (название может не соответствовать, поэтому искать лучше по полю Location Info), нажать Set Mask и выбрать ядро на которое будет назначен драйвер. Выбирать надо на любое ядро отличное от первого.

Пример установки ядра для драйвера устройства в утилите Interrupt Affinity Policy Tool

⚠️ На CPU, где включен Hyper-Threading [?] / SMT [?], ядра и потоки в программе чередуются – CPU 0 - Ядро 1, CPU 1 - Поток 1, CPU 2 - Ядро 2, CPU 3 - Поток 2 и т.д., соответственно, чтобы выбрать третье ядро надо указать CPU 4 и CPU 5. На CPU без Hyper-Threading/SMT ядра, само собой, указаны без потоков.

Сообщение о перезагрузке драйвера в утилите Interrupt Affinity Policy Tool

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

‼️ Нельзя переносить все драйверы на другие ядра, этим вы лишь можете добиться появления BSOD [?]!

⚠️ Данная настройка сбрасывается на дефолтное значение после обновления драйвера nVidia!