#cpp #sfml
Работая над меню игры, которая создаётся с помощью SFML, столкнулся с проблемой "пустой" загрузки процессора в циклах, которые не высчитывают что-либо в прямом значении этого слова, а просто ожидают каких-либо событий от пользователя и меняют состояние (выходят из него или опускаются глубже во внутренние циклы) только тогда, когда что-то происходит, а до тех пор выводят изображение на экран и тому подобное, тем самым нагружая процессор на ~20-30%, хотя реально такие мощности не используются. Пытался это решить с помощью ожидания события (waitEvent), а не его "вылова" (pollEvent), но это просто стопорило программу. Может быть как-то неправильно этим пользовался. Да и не только в данном проекте столкнулся с подобным. В других так же, где были аналогичные циклы. Сам "скелет" подобного цикла выглядит примерно так: while (window.isOpen()) { sf::Event event; while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) window.close(); } window.clear(); //window.draw(something); window.display(); } Как решать подобные проблемы? Уместно ли будет использовать таймеры или функции типа Sleep()? Какие технологии можно применять для оптимизации подобных ситуаций?
Ответы
Ответ 1
У класса окна sf::Window имеется метод setFramerateLimit. Но он не гарантирует тот факт что частота кадров будет равна той, которую вы установили. Т.к. он все так же использует функцию sf::sleep. Ограничивает частоту кадров до максимальной фиксированной частоты. Если установлен лимит, окно будет использовать небольшую задержку после каждого вызова display(), чтобы гарантировать что текущий кадр длился достаточно долго, и соответствовать пределу частоты кадров. SFML будет пытаться соответствовать заданному пределу, насколько это возможно, но так как он внутренне использует sf::sleep, точность которого зависит от базовой ОС, результаты могут быть немного неточными (например, вы можете получить 65 кадров в секунду при запросе 60).Ответ 2
Небольшое вступление. Процессор всегда загружен на 100%, даже если он ничего не делает. Если в диспетчере написано, что процессор загружен на 1%, это лишь значит, что процессор 99% времени работает в холостую, ожидая полезную нагрузку. У разных процессоров есть различные механизмы торможения. Одни процессоры могут полностью уснуть, ожидая прерывания на каком-нибудь порте, другие - предоставляют специализированные команды, которые понижают частоту камня в тех или иных условиях. Если вас интересует, как ограничивают скорость работы главного цикла (например, в играх), то там имеется несколько способов. Каждый со своими клопами. В простых случаях для снижения потока пустой информации через процессор можно использовать Sleep(1); или что-то аналогичное. В сложных стратегиях управления работой процессора можно усыплять процесс/поток с последующим пробуждением по событию + срабатыванию таймера ядра ОС. Важно понимать, что отрисовка и просчеты должны происходить независимо от факта поступления событий, потому что ваше окно может не получать никаких событий несколько секунд, а потом получит 1000 событий за 1 мс. Часто - и обработка событий, и просчеты, и отрисовка - должны происходить независимо. Иногда для каждого процесса используются сложные алгоритмы планирования и предсказания. Это делается для сглаживания поведения игры на различных устройствах.Ответ 3
Решил данную проблему просто заменой внутреннего цикла обработки событий на условный оператор, который ожидает событие и потом его обрабатывает во вложенных операторах: sf::Event event; if (window.waitEvent(event)) { ... } Получается, что программа на данной строке будет просто ожидать любого события (нажатие клавиши, движение курсора мыши и тд) и дальнейшие итерации основного цикла будут происходить только тогда, когда происходит что-либо, без "пустой" нагрузки на процессор постоянными не контролируемыми итерациями. По сравнению с предыдущим вариантом, нагрузка снизилась до 1-2% без какой-либо потери функциональности.
Комментариев нет:
Отправить комментарий