Qpc таймер windows 10

Содержание
  1. HPET: что это и как с его помощью оптимизировать Windows
  2. Функции аппаратного таймера
  3. Как сменить значение таймера и ускорить Windows
  4. Как ускорить компьютер в играх? Отключите одну настройку
  5. Что такое HPET?
  6. Тестирование и сравнение
  7. Как отключить/включить HPET?
  8. 1. Через командную строку Windows
  9. Через диспетчер устройств
  10. Через сторонние твикеры/бенчмарки
  11. Бонусом
  12. Как увеличить FPS в играх, отключив HPET?
  13. High Precision Event Timer (HPET) – высокоточный таймер событий
  14. Что будет если отключить HPET?
  15. Увеличится ли fps в играх и приложениях при отключении hpet?
  16. Безопасно ли отключать HPET?
  17. При отключении HPET могут ли быть проблемы в онлайн играх?
  18. Если, отключив HPET, увеличивается фпс, то зачем вообще его нужно включать? И зачем тогда он включен по умолчанию?
  19. Как отключить HPET?
  20. Способ 1. Через BIOS или UEFI
  21. Способ 2. Через командную строку
  22. Способ 3. Используя диспетчер задач Windows
  23. Нужно ли отключать HPET?
  24. Что значит HPET Mode? HPET mode 32 или 64 что выбрать?
  25. Внимание пользователей ноутбуков
  26. Системный таймер в Windows: большое изменение
  27. Прерывания таймера и смысл их существования
  28. Десятилетия безумия
  29. timeGetTime
  30. Новая недокументированная реальность
  31. Научный эксперимент
  32. Последствия

HPET: что это и как с его помощью оптимизировать Windows

HPET был введен компаниями Intel и Microsoft в 2005 году. Это аппаратный таймер, который находится в пределах южного моста – компонента, отвечающего за связь процессора с жестким диском, видеокартой, оптическим приводом и другими устройствами для обеспечения максимальной пропускной способности.

Функции аппаратного таймера

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

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

Симптомом неправильной работы HPET (или полного его бездействия) являются, например, регулярные секундные зависания Windows. Компьютер со временем начинает медленно работать. В такой ситуации следует задуматься над изменением параметров указанной функции.

Как сменить значение таймера и ускорить Windows

Сначала нужно определить, поддерживает ли ее в целом наша платформа. Здесь все просто – Windows Vista и новые версии поддерживают HPET, XP делает это частично, старые «окна» вообще не используют этот дополнительный таймер. В случае сомнений следует заглянуть в BIOS.

В дополнительных параметрах (Advanced) должна быть опция Configuration PCH или HPET Mode (название может немного отличаться в зависимости от версии BIOS и производителя материнской платы). Нам нужно найти High Precision Timer, ACPI HPET Table или похожее. Здесь можно ее включить или отключить.

Тем не менее Windows имеет тенденцию к перезаписи установленных параметров и использовать HPET, несмотря на настройки в Биосе. Поэтому после загрузки системы нужно открыть командную строку с правами администратора. Для ее вызова в Windows 10 кликните правой кнопкой на меню Пуск и выберите соответствующий пункт.

HPET сможете включить с помощью команды:

bcdedit /set useplatformclock true

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

bcdedit /deletevalue useplatformclock

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

Важно: в этом обзоре речь не идет о том, что HPET должен быть полностью включен или выключен. Если вы столкнулись с проблемами зависания системы – медленно открываются программы или рывки в работе компьютера — то следует проверить, работает ли HPET, и попробовать разные настройки. Полученный результат будет зависеть от точного определения причины указанной проблемы.

Как ускорить компьютер в играх? Отключите одну настройку

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

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

Опытом настройки ПК и инструкциями мы делимся регулярно в нашем Telegram-канале. Сегодня расскажем про то, как удалось разогнать связку из процессора Intel Core i5-9600KF, материнской платы Asus Prime Z390-P и видеокарты Sapphire Pulse Radeon RX 5700 XT.

Впрочем, тут стоит ещё проверить, изначально, включена ли та самая настройка у вас или уже деактивирована по-умолчанию. Отдадим почести парням из PRO Hi-Tech, после видео которых мы решили провести этот эксперимент на своей системе и поделиться результатами с нашими читателями.

Что такое HPET?

Сегодня схема HPET интегрирована в чип южного моста. Если ранее можно было управлять HPET через BIOS, то современные версии уже в большинстве случаев не дают такой настройки. К старым операционным системам в данном случае стоит относить от Microsoft те, что вышли раньше Windows 7.

Может случиться, что HPET активна на аппаратном уровне и одновременно включена в Windows. Отключение её в системе может сказаться на производительности.

Тестирование и сравнение

Для проверки теории использовали встроенный бенчмарк Metro Exodus, выбрав Extreme-профиль настроек графики, DirectX11 и разрешение 1920×1080 пикселей. Слева направо результаты с выключенным параметром HPET и затем включённым.

Кроме того, прогнали тест в бенчмарке TimerBench 1.3.3.

HPET активна. Здесь уже для бенчмарка выбрали разрешение 3840×2160 пикселей.

Те же условия, но HPET деактивирована.

Как отключить/включить HPET?

Мы нашли 3 способа.

1. Через командную строку Windows

Запустите командную строку от имени администратора. Открываем меню пуск, набираем с клавиатуры «cmd», выбираем администраторский вариант.

Читайте также:  Драйвер для принтера canon mf4430 windows 10

Чтобы отключить введите команды:

bcdedit /set disabledynamictick yes

Чтобы заново включить используйте:

bcdedit /set disabledynamictick no

Через диспетчер устройств

Используем сочетание клавиш Win+Break, затем в открывшемся окне выбираем ссылку «Диспетчер устройств». В разделе «Системные устройства» находим «High Precision Event Timer» (Высокоточный таймер событий), открываем контекстное меню по клику правой кнопкой мыши и деактивируем устройство.

Через сторонние твикеры/бенчмарки

Мы использовали TimerBench 1.3.3, который позволяет управлять HPET через свой интерфейс. У вас тоже появится такая возможность, если решите проверить работу на своей системе и сравнить результаты до и после. Скачать приложение можно по ссылке.

Бонусом

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

Если вам интересны новости мира ИТ также сильно, как нам, подписывайтесь на наш Telegram-канал. Там все материалы появляются максимально оперативно. Или, может быть, вам удобнее «Вконтакте» или Twitter? Мы есть также в Facebook.

Как увеличить FPS в играх, отключив HPET?

Немногие знают, как можно увеличить FPS в играх, отключив HPET. В это статье разберём, что такое HPET и что будет, если отключить эту функцию, а также, безопасно ли это.

High Precision Event Timer (HPET) – высокоточный таймер событий

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

Отложенный вызов процедур (задержка DPC) позволяет программам быстро помещать действия в очередь в планировщике процессора, которые через какое-то время будут обработаны.

Например, отрисовка видеокадра (video frame) на экране может быть выполнена, как только данные будут готовы и время кадра (frame time) достигнуто. Конечно, всё это делается за какие-то доли секунд и не замечается многими людьми.

Что будет если отключить HPET?

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

1000 секунда = 1 миллисекунда
HPET ON: задержка между 100-150 мс
HPET OFF: задержка между 5-15 мс

Выходит, что с включённой функцией таймера HPET происходит потеря 3-4 кадра в секунду, соответственно, с выключенной функцией снижается вероятность «зависания».

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

Увеличится ли fps в играх и приложениях при отключении hpet?

Отключение этого параметра (даже через командную строку) может существенно повлиять на производительность в играх и приложениях. В некоторых случаях ваш FPS может сильно увеличиться (например, с 30 до 100).

Безопасно ли отключать HPET?

Да, это абсолютно безопасно. Это ничего не повредит и не приведёт к нежелательным побочным эффектам. Вы всегда сможете вернуть всё обратно.

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

При отключении HPET могут ли быть проблемы в онлайн играх?

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

Если, отключив HPET, увеличивается фпс, то зачем вообще его нужно включать? И зачем тогда он включен по умолчанию?

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

Как отключить HPET?

Способ 1. Через BIOS или UEFI

Очень часто таймер можно отключить через BIOS или UEFI, найдя, к примеру, функцию HPET Support или High Precision Event Timer (название может немного отличаться, в зависимости от вашей материнской платы):

Способ 2. Через командную строку

В Windows 10 также можно отключить HPET через командную строку от имени администратора после ввода следующих команд:

bcdedit /deletevalue useplatformclock
bcdedit /set disabledynamictick yes

Чтобы внести изменения необходимо перезагрузить компьютер.

Если вы хотите повторно включить HPET, используйте следующие команды:

bcdedit /set useplatformclock true
bcdedit /set disabledynamictick no

Способ 3. Используя диспетчер задач Windows

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

Нужно ли отключать HPET?

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

Читайте также:  Драйверы hp laserjet m1005 mfp для windows 10 x64

Что значит HPET Mode? HPET mode 32 или 64 что выбрать?

Если вы включили таймер, то в некоторых случаях вы сможете выбрать mode 32-bit или 64-bit, данная опция всего-навсего уточняет режим работы счётчиков: 32-разрядный или 64-разрядный. Если у вас установлена 32-разрядная система, то выбирайте 32-bit mode, а если 64-разрядная, то 64-bit mode.

Внимание пользователей ноутбуков

Отключение HPET, уменьшение разрешения таймера в Windows 10 приведет к увеличению расхода батареи. А как сохранить батарею ноутбука и увеличить продолжительность его работы читайте в моей статье.

Системный таймер в Windows: большое изменение

Поведение планировщика Windows значительно изменилось в Windows 10 2004 без каких-либо предупреждений и изменения документации. Вероятно, это поломает несколько приложений. Такое происходит не первый раз, но эта перемена посерьёзнее.

Если вкратце, то вызовы timeBeginPeriod из одного процесса теперь влияют на другие процессы меньше, чем раньше, хотя эффект ещё присутствует.

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

Прерывания таймера и смысл их существования

Во-первых, немного контекста о дизайне операционных систем. Желательно, чтобы программа могла засыпать, а позже — просыпаться. На самом деле это не следует делать очень часто — потоки обычно ждут событий, а не таймеров, — но иногда необходимо. Итак, в Windows есть функция Sleep — передайте ей желаемую продолжительность сна в миллисекундах, и она разбудит процесс:

Стоит подумать о том, как это реализуется. В идеале при вызове Sleep(1) процессор переходит в спящий режим. Но как операционная система разбудит поток, если процессор спит? Ответ — аппаратные прерывания. ОС программирует микросхему — аппаратный таймер, который затем запускает прерывание, которое пробуждает процессор, и ОС затем запускает ваш поток.

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

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

Существует множество способов объединения пробуждений, но основной механизм в Windows — глобальное прерывание таймера, тикающего с постоянной скоростью. Когда поток вызывает Sleep(n), то ОС запланирует запуск потока сразу после первого прерывания таймера. Это означает, что поток может в конечном итоге проснуться немного позже, но Windows — это не ОС реального времени, она вообще не гарантирует определённое время пробуждения (в это время ядра процессора могут быть заняты), поэтому вполне нормально проснуться чуть позже.

Интервал между прерываниями таймера зависит от версии Windows и железа, но на всех моих машинах он по умолчанию составлял 15,625 мс (1000 мс/64). Это означает, что если вызвать Sleep(1) в какое-то случайное время, то процесс будет разбужен где-то между 1,0 мс и 16,625 мс в будущем, когда сработает следующее прерывание глобального таймера (или через одно, если это сработало слишком рано).

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

Некоторым программам не подходит такой большой разброс в задержках ожидания (WPF, SQL Server, Quartz, PowerDirector, Chrome, Go Runtime, многие игры и т. д.). К счастью, они могут решить проблему с помощью функции timeBeginPeriod, которая позволяет программе запросить меньший интервал. Есть также функция NtSetTimerResolution, которая позволяет устанавливать интервал меньше миллисекунды, но она редко используется и никогда не требуется, поэтому не буду больше её упоминать.

Десятилетия безумия

Вот сумасшедшая вещь: timeBeginPeriod может вызвать любая программа, и она изменяет интервал прерывания таймера, при этом прерывание таймера — это глобальный ресурс.

Представим, что процесс А находится в цикле с вызовом Sleep(1). Это неправильно, но это так, и по умолчанию он просыпается каждые 15,625 мс, или 64 раза в секунду. Затем появляется процесс B и вызывает timeBeginPeriod(2). Это заставляет таймер срабатывать чаще, и внезапно процесс А просыпается 500 раз в секунду вместо 64-х раз в секунду. Это безумие! Но именно так всегда работала Windows.

В этот момент, если бы появился процесс C и вызвал timeBeginPeriod(4), это ничего бы не изменило — процесс A продолжал бы просыпаться 500 раз в секунду. В такой ситуации правила устанавливает не последний вызов, а вызов с минимальным интервалом.

Таким образом, вызов timeBeginPeriod от любой работающей программы может установить глобальный интервал прерывания таймера. Если эта программа завершает работу или вызывает timeEndPeriod, то вступает в силу новый минимум. Если одна программа вызывает timeBeginPeriod(1), то теперь это интервал прерывания таймера для всей системы. Если одна программа вызывает timeBeginPeriod(1), а другая timeBeginPeriod(4), то всеобщим законом становится интервал прерывания таймера в одну миллисекунду.

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

Одним из приложений, которому необходимо планирование на основе таймера, является веб-браузер. В стандарте JavaScript есть функция setTimeout, которая просит браузер вызвать функцию JavaScript через несколько миллисекунд. Для реализации этой и других функций Chromium использует таймеры (в основном WaitForSingleObject с таймаутами, а не Sleep). Это часто требует повышенной частоты прерываний таймера. Чтобы это не слишком сказывалось на времени автономной работы, Chromium недавно модифицировали таким образом, чтобы при работе от батареи частота прерываний таймера не превышала 125 Гц (интервал 8 мс).

Читайте также:  Linux или windows 10 home

timeGetTime

Функция timeGetTime (не путать с GetTickCount) возвращает текущее время, обновлённое прерыванием таймера. Процессоры исторически не очень хороши в ведении точного времени (их часы специально колеблются, чтобы не служить FM-передатчиками, и по другим причинам), поэтому для поддержания точного времени CPU часто полагаются на отдельные генераторы тактовых импульсов. Чтение с этих чипов стоит дорого, поэтому Windows поддерживает 64-битный счётчик времени в миллисекундах, обновляемый прерыванием таймера. Этот таймер хранится в общей памяти, поэтому любой процесс может дёшево считывать оттуда текущее время, не обращаясь к генератору тактовых импульсов. timeGetTime вызывает ReadInterruptTick, который по сути просто считывает этот 64-битный счётчик. Все просто!

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

Новая недокументированная реальность

С выпуском Windows 10 2004 (апрель 2020 года) некоторые из этих механизмов слегка изменились, но очень запутанным образом. Сначала появились сообщения, что timeBeginPeriod больше не работает. На самом деле всё оказалось куда сложнее.

Первые эксперименты дали смешанные результаты. Когда я запустил программу с вызовом timeBeginPeriod(2), то clockres показал интервал таймера 2,0 мс, но отдельная тестовая программа с циклом Sleep(1) просыпалась около 64 раз в секунду вместо 500 раз, как в предыдущих версиях Windows.

Научный эксперимент

Тогда я написал пару программ для изучения поведения системы. Одна программа (change_interval.cpp) просто сидит в цикле, вызывая timeBeginPeriod с интервалами от 1 до 15 мс. Она удерживает каждый интервал в течение четырёх секунд, а затем переходит к следующему, и так по кругу. Пятнадцать строк кода. Легко.

Другая программа (measure_interval.cpp) запускает несколько тестов для проверки, как её поведение изменяется при изменении change_interval.cpp. Программа отслеживает три параметра.

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

@FelixPetriconi провёл для меня тесты на Windows 10 1909, а я провёл тесты на Windows 10 2004. Вот очищенные от случайных флуктуаций результаты:

Это означает, что timeBeginPeriod по-прежнему устанавливает интервал глобального таймера во всех версиях Windows. Из результатов timeGetTime() можно сказать, что прерывание срабатывает с такой скоростью по крайней мере на одном ядре процессора, и время обновляется. Обратите также внимание, что 2.0 в первой строке для 1909 года тоже было 2.0 в Windows XP, затем 1.0 в Windows 7/8, а затем вроде опять вернулось к 2.0?

Однако поведение планировщика резко меняется в Windows 10 2004. Ранее задержка для Sleep(1) в любом процессе просто равнялась интервалу прерывания таймера, за исключением timeBeginPeriod(1), давая такой график:

В Windows 10 2004 соотношение между timeBeginPeriod и задержкой сна в другом процессе (который не вызывал timeBeginPeriod) выглядит странно:

Точная форма левой части графика неясна, но она определённо уходит в противоположную сторону от предыдущего!

Последствия

Как было указано в обсуждении reddit и hacker-news, вероятно, левая половина графика представляет собой попытку максимально точно имитировать «нормальную» задержку, учитывая доступную точность глобального прерывания таймера. То есть с интервалом прерывания 6 миллисекунд задержка происходит примерно на 12 мс (два цикла), а с интервалом прерывания 7 миллисекунд — примерно на 14 мс (два цикла). Однако измерение фактических задержек показывает, что реальность ещё более запутанна. При прерывании таймера, установленном на 7 мс, задержка Sleep(1) в 14 мс даже не самый распространённый результат:

Некоторые читатели могут обвинить случайный шум в системе, но когда частота прерывания таймера 9 мс и выше, шум равен нулю, так что это не может быть объяснением. Попробуйте сами запустить обновлённый код. Особенно противоречивыми кажутся интервалы прерывания таймера от 4 мс до 8 мс. Вероятно, измерения интервалов следует выполнять с помощью QueryPerformanceCounter, поскольку на текущий код беспорядочно влияют изменение правил планирования и изменение точности таймера.

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

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

  • Программа может случайно предположить, что у Sleep(1) и timeGetTime одинаковое разрешение, а это теперь не так. Хотя, такое предположение кажется маловероятным.
  • Программа может зависеть от маленького разрешения таймера, которого не получает. Было несколько сообщений о такой проблеме в некоторых играх — есть инструмент под названием Windows System Timer Tool и ещё один под названием TimerResolution 1.2. Они «исправляют» эти игры, повышая частоту прерываний таймера. Видимо, эти исправления больше не будут работать или будут работать не так хорошо. Возможно, это заставит разработчиков игр выпустить правильные патчи, но до тех пор изменение вызывает проблемы обратной совместимости.
  • В многопроцессной программе главная управляющая программа может повысить частоту прерываний таймера, а затем ожидать, что это повлияет на планирование дочерних процессов. Раньше это было разумное предположение, но теперь оно не работает. Именно так я сам узнал об этой проблеме. Продукт, о котором идёт речь, теперь вызывает timeBeginPeriod в каждом процессе, так что всё в порядке, но несколько месяцев программное обеспечение плохо работало по непонятной причине.

Оцените статью