Нативные приложения - снятие нагрузки?

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Seenkao
энтузиаст
Сообщения: 568
Зарегистрирован: 01.04.2020 02:37:12
Контактная информация:

Нативные приложения - снятие нагрузки?

Сообщение Seenkao »

Всем привет. Наверняка многим известно, что я занимаюсь доработкой ZenGL и я давно ещё искал путь ограничения ФПС, ещё задолго до того как начал заниматься самим ZenGL.
И вот, разбираясь что к чему и получив ограничение которое искал, я обнаружил, что очень сильно стал загружаться процессор, аж до 25%... в чём же дело? И стал ковырять код дальше, сначала подумав, что может где-то не то наковырял...

Так вот, слишком долгое вступление. :)

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

Код: Выделить всё

var
  newTime, oldTime: Double;
  maxFPS: single = 1000 / 30;      // 30 FPS - ограничиваем
...
 if winON then
begin
  if PeekMessage(...) then
  begin
    TranslateMessage(msg);
    DispatchMessage(msg);
  end
  else begin    // основной опрос вашей программы
    newTime := GetTickCount;
    // выставляем (проверяем) ограничение
    if newTime >= oldTime + maxFPS then
    begin
      Draw();                          // стандартная работа программы
      oldTime := oldTime + maxFPS;
      ...
    end

// и вот тут код, который вдруг разгружает систему почти в нуль,
    else
      Sleep(1);
  end;
end;
...


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

P.S. нашёл ошибку, исправил )))) в том коде что выложил.

P.P.S. Касается в основном Windows.
Последний раз редактировалось Seenkao 17.08.2020 23:31:22, всего редактировалось 1 раз.
Аватара пользователя
runewalsh
энтузиаст
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Сообщение runewalsh »

while true do PeekMessageW — крутится столько раз в секунду, сколько сможет, и занимает 1 ядро процессора вплоть до 100%, совсем как while true do inc(i).
Sleep — говорит системе снять твой поток с выполнения на указанное время, освободив ядро процессора для других потоков, а если работы нет — усыпив его.
Спящее ядро не потребляет энергию, не греется и учитывается как 0% нагрузка. Собственно, в каждый момент времени ядро либо делает что-то и тем самым загружено на 100%, либо спит и загружено на 0%, промежуточные показатели, которые ты видишь — усреднённое состояние в течение некоторого времени, например, 1 секунды.

Но while true do begin PeekMessageW(...); Sleep(1); end; — отвратительное решение, подробнее в этой статье. Вкратце: если бы каждая запущенная в твоей системе программа крутилась в цикле, в котором она засыпает на 1 миллисекунду, просыпается, что-то проверяет и снова засыпает — то на ней можно было бы жарить яичницу, даже когда ничего не запущено.
Правильно: while true do begin GetMessageW(...); ... end;
GetMessageW, если сообщений нет, сама усыпит поток и разбудит, когда придёт сообщение. Если при этом нужно уметь будить его и самостоятельно — можно использовать MsgWaitFor*-ожидания или пользовательские оконные сообщения WM_APP+x (ими можно будить спящую GetMessageW).
В крайнем случае спать нужно не 1 миллисекунду, а max(0, 1 / maxFpms - passed).
Seenkao
энтузиаст
Сообщения: 568
Зарегистрирован: 01.04.2020 02:37:12
Контактная информация:

Сообщение Seenkao »

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

Это предотвращается программно.

Правильно: while true do begin GetMessageW(...); ... end;

я думаю не стоит говорить "правильно" или "не правильно" использовать те или иные функции, не зная как работает программа.

Но теперь вопрос появляется, есть ли аналог Sleep? И твой пост заставляет задуматься!!! :)

P.S. И, надо понимать, что в данном случае Sleep(1) "подменяет" прорисовку экрана (а может ещё какой код), если мы не вышли на время прорисовки, а не сопровождает код прорисовки.
olegy123
долгожитель
Сообщения: 1643
Зарегистрирован: 25.02.2016 11:10:20

Сообщение olegy123 »

Seenkao писал(а):Я не знаю, знают об этом или нет, но я ни где не видел, чтоб так можно было разгрузить систему. Получается, если мы не прорисовываем ни чего, то заставляем процессор выждать милисекунду.
Это вообще правильно?

Можно, и в некоторых случаях правильно и просто. Есть приложения которые работают по запросу - практически все гуи приложения, иначе калькулятор грузил проц на все 100.
Но в других лучше так не использовать, потому что на 1ms теряешь управление. 1ms это очень много.

Кстати еще выход снизить нагрузку - это уменьшить приоритет потока.

Добавлено спустя 11 минут 8 секунд:
Seenkao писал(а):Но теперь вопрос появляется, есть ли аналог Sleep?
смотришь на системы реального времени? где требуется жесткий регламент таймеров?
В линухе само ядро работает на 1Кгц это максимум что можегешь получить по переключениям, с учетом того что тебе никто не будет мешать..
если хочешь иметь импульсы повыше -их можно извне.. смотри в сторону STM32/FPGA

Добавлено спустя 4 минуты 9 секунд:
В винде есть счетчик тактов по процессору, но он от процика к процику разный.
Seenkao
энтузиаст
Сообщения: 568
Зарегистрирован: 01.04.2020 02:37:12
Контактная информация:

Сообщение Seenkao »

olegy123 писал(а):Можно, и в некоторых случаях правильно и просто. Есть приложения которые работают по запросу - практически все гуи приложения, иначе калькулятор грузил проц на все 100.
Но в других лучше так не использовать, потому что на 1ms теряешь управление. 1ms это очень много.

Благодарю! Я понял и данная проблема решена и для меня подходит.
Если я использую цикл и PeekMessage, то использую Sleep, а если работаю от системы используя GetMessage, то от Sleep надо отказываться.

Добавлено спустя 4 минуты 5 секунд:
Seenkao писал(а):смотришь на системы реального времени? где требуется жесткий регламент таймеров?
В линухе само ядро работает на 1Кгц это максимум что можегешь получить по переключениям, с учетом того что тебе никто не будет мешать..
если хочешь иметь импульсы повыше -их можно извне.. смотри в сторону STM32/FPGA

Добавлено спустя 4 минуты 9 секунд:
В винде есть счетчик тактов по процессору, но он от процика к процику разный.

это наверно на будущее оставлю. Пока смысла нет совсем заморачиваться.
olegy123
долгожитель
Сообщения: 1643
Зарегистрирован: 25.02.2016 11:10:20

Сообщение olegy123 »

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

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

Добавлено спустя 11 минут 17 секунд:
с проблемой точного подсчета времени я столкнулся когда нужно было синхронизировать работу двух компьютеров, штатных средств нет.
Ethernet не самый быстрый синхронизатор. там пакет уходит когда микросхема решит сбросить буфер, и наоборот, известить CPU о входящих пакетов.
mig-31
постоялец
Сообщения: 224
Зарегистрирован: 14.07.2011 13:46:48

Сообщение mig-31 »

Seenkao писал(а):Всем привет. Наверняка многим известно, что я занимаюсь доработкой ZenGL и я давно ещё искал путь ограничения ФПС, ещё задолго до того как начал заниматься самим ZenGL.
И вот, разбираясь что к чему и получив ограничение которое искал, я обнаружил, что очень сильно стал загружаться процессор, аж до 25%... в чём же дело? И стал ковырять код дальше, сначала подумав, что может где-то не то наковырял...


У меня есть приложение для Линух, в кoтором у меня в 2-х TThread крутится в циклах опрос двух устройств по последовательному порту и Telnet без sleep. Загрузки процесора на 25% я не наблюдаю.
olegy123 писал(а):В линухе само ядро работает на 1Кгц это максимум что можегешь получить по переключениям, с учетом того что тебе никто не будет мешать..
если хочешь иметь импульсы повыше -их можно извне.. смотри в сторону STM32/FPGA

Немного исправлю. Ядра по умолчанию, коплирируются на 1кГц и этого достаточно для большинства задач. Для мультимедия этого мало, поэтому есть возможность собрать ядро с таймером 1МГц и почти во всех дистрибутивах оно есть в репозитории. Есть также патч реального времени для ядра (soft realtime).
Seenkao
энтузиаст
Сообщения: 568
Зарегистрирован: 01.04.2020 02:37:12
Контактная информация:

Сообщение Seenkao »

Ответ на первоначальный вопрос, касается он больше Windows (на Linux не надо ни чего придумывать), Sleep(1) можно использовать только для прорисовки кадров не более 60Гц. Как только мы увеличиваем граничную частоту больше 60, есть достаточный шанс, что приложение начнёт лагать. Для небольших процессов это возможно не критично, но для приложений, граничащих по работе с частотой обновления монитора, наверняка вызовет глюки.

Sleep(1), может вызвать задержку до 16 милисекунд. (что для 60 Гц как раз и не критично).
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

Seenkao писал(а): Наверняка многим известно, что я занимаюсь доработкой ZenGL и я давно ещё искал путь ограничения ФПС

Код: Выделить всё

scr_SetVSync(true);

?
Seenkao
энтузиаст
Сообщения: 568
Зарегистрирован: 01.04.2020 02:37:12
Контактная информация:

Сообщение Seenkao »

скалогрыз, наверно всё-таки стоит знать как работает внутренний код. Тот метод, по ограничению FPS, не следит за тем, отправляются данные на видеокарту или нет. На системное FPS, ни как не повлияет. А меня интересует, чтоб программа могла спокойно работать не только на последних супер-мощных компьютерах, но и на тех компьютерах, которые "вышли из моды" - устаревшие модели.
И ваше предложение ни как не решит проблем связанных со старыми компьютерами. :)
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

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

я боюсь, что ZenGL может спокойно работать не только на тех кто "вышли из моды", но даже на тех моделях, которые "вышли из жизни".

ты можешь объяснить, какие такие тормоза будут, если пограмма умудряется выдавать очень большой FPS?
Seenkao
энтузиаст
Сообщения: 568
Зарегистрирован: 01.04.2020 02:37:12
Контактная информация:

Сообщение Seenkao »

Изображение может дёргаться. Надо будет подгонять кадры, а это хуже некуда.

Я буду обходить этот момент. Просто введу проверку что если ФПС больше 60, то Sleep(1) срабатывать вообще не будет. И это так же будет полезно и для слабых компьютеров, случайный заход на долгую задержку будет исключён.

Но вероятнее всего надо будет проверять параметры системы и так же исключать Sleep(1), при граничных нагрузках.

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

Не на всех будут. Только на моделях у которых видеокарта поддерживает OpenGL и на компьютерах где OpenGL не поддерживает ***ChoisePixelFormat надо делать доработку на проверку данной функции.
MysticCoder
постоялец
Сообщения: 154
Зарегистрирован: 14.09.2013 00:20:28

Сообщение MysticCoder »

Похоже, что TC сам придумал себе несуществующие проблемы и сам же пытается их героически преодолеть. Еще рассмотри разницу между Sleep(0) и Sleep(1).
Seenkao
энтузиаст
Сообщения: 568
Зарегистрирован: 01.04.2020 02:37:12
Контактная информация:

Сообщение Seenkao »

MysticCoder, не существующую? :)
Может вы мне тогда объясните разницу в том, что игры на старых компьютерах потребляют почти всё процессорное время, а при вводе данного кода, те же компьютеры почти бездействуют, но вывод и работа программы осуществляется в том же режиме?!

Я бы очень хотел посмотреть на то как вы справляетесь с этой проблемой.
MysticCoder
постоялец
Сообщения: 154
Зарегистрирован: 14.09.2013 00:20:28

Сообщение MysticCoder »

Sleep это легальный способ и его не использует разве только ленивый. Если делать приложению нечего, то логично отдать управление ОС, что и делает Sleep. Загрузка процессора это не что то волшебное, нельзя сказать, что вот эта процедура загружает процессор на 17 процентов, потому что я ее оптимизировал. Пока работает процедура она загружает проц на 100 процентов, если конечно же она не передаёт управление ОС внутри себя всякими блокирующими операциями типа чтений файлов или сокетов.
Если не передавать управление ОС, то загрузка будет 100 процентов. Если передавать управление ОС, то загрузка будет от 0 до 100 процентов.
При 0 рендер и код логики выполняются за пренебрежительно малое время(да-да, старые игры реально могут тратить очень мало процессорного времени). При 100 процентах рендер или/и логика занимают ощутимое время по сравнению со временем потраченным на Sleep.
Велосипедов из сообщений и прочего на замену Sleep городить не надо. Если критичны микросекунды, то не отдаешь управление ОС и миришься со 100 процентной загрузкой проца. Если не критичны, то юзаешь Sleep и спишь спокойно.
Ну и разницу между Sleep(0) и Sleep(1) все таки нагугли.
Ответить