Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Nested pollEvent spikes CPU  (Read 1777 times)

0 Members and 1 Guest are viewing this topic.

mendlo

  • Newbie
  • *
  • Posts: 3
    • View Profile
Nested pollEvent spikes CPU
« on: June 15, 2015, 10:44:14 am »
Hello,

I'm having trouble drawing something in the window upon an event, holding that display, then resetting the display upon another event. I've come up with a solution, however it causes a high spike in CPU utilization. In the code snippet below, the CPU spikes and remains high when [Space] is pressed. The CPU spike goes away when [Escape] is pressed.

How can I implement a better solution for this? Any help appreciated.

#include <SFML/Graphics.hpp>
#include "ResourcePath.hpp"

int main() {
    sf::RenderWindow window(sf::VideoMode(480, 320), "SFML Window");
    window.setFramerateLimit(20);

    sf::Font font;
    if (!font.loadFromFile(resourcePath() + "sansation.ttf")) {
        return 0;
    }
    sf::Text text;
    text.setFont(font);
    text.setCharacterSize(50);
    text.setStyle(sf::Text::Regular);
    text.setColor(sf::Color::Blue);

    while (window.isOpen()) {
        window.clear();
       
        text.setString("Hello SFML");
        window.draw(text);
       
        window.display();

        sf::Event event;
        while (window.pollEvent(event)) {

            if (event.type == sf::Event::Closed) {
                window.close();
                exit(0);
            }

            if (event.type == sf::Event::KeyPressed) {
               
                if (event.key.code == sf::Keyboard::Space) {
                    window.clear();
                   
                    text.setString("You pressed space");
                    window.draw(text);
                   
                    window.display();
                   
                    bool wait = true;
                    while(wait) {
                   
                        while (window.pollEvent(event)) {
                            if (event.type == sf::Event::Closed) {
                                window.close();
                                exit(0);
                            }
                           
                            if (event.type == sf::Event::KeyPressed) {
                                if (event.key.code == sf::Keyboard::Escape) {
                                    wait = false;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return 0;
}
 
« Last Edit: June 15, 2015, 11:50:44 am by mendlo »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Nested pollEvent spikes CPU
« Reply #1 on: June 15, 2015, 10:47:22 am »
pollEvent is not supposed to get nested. There should only be one call to it.
If you want to check certain "states", use variables to store things (e.g. whether a key has been pressed).

Also you can't check for the key code without making sure that a key has been pressed.

I suggest you re-read the official tutorial about events. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

mendlo

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Nested pollEvent spikes CPU
« Reply #2 on: June 15, 2015, 11:49:24 am »
Thank you for the quick and friendly reply!

Is this the tutorial you're referring to? http://www.sfml-dev.org/tutorials/2.0/window-events.php

I'd like to find more information about using the "states" you referred to.

Not checking for KeyPressed in the second loop was a silly mistake when I shrunk my code down into the snippet above. I'll correct that in my OP.

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Nested pollEvent spikes CPU
« Reply #3 on: June 15, 2015, 04:48:49 pm »
Latest version of the tutorial: http://www.sfml-dev.org/tutorials/2.3/window-events.php

As far as the 'states' eXploit3r talks about; it's as simple as remembering that a key has been pressed and then checking the variable - like a "bool escapePressed" that you keep updated with true/false according to events received.
@eXploit3r if that's not what you meant; please correct me :)

Edit: and by the way, "x-mas trees" like this are almost always an indication that you are doing something wrong:
Quote
                                }
                            }
                        }
                    }
                }
            }
        }
    }
« Last Edit: June 15, 2015, 08:14:53 pm by Jesper Juhl »

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Nested pollEvent spikes CPU
« Reply #4 on: June 15, 2015, 07:49:03 pm »
The comments above are what you should actually do but the reason behind the CPU usage rising is that the loop that waits for the Escape key is continuous. There are no window updates and therefore the window's framerate limit doesn't take effect.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

mendlo

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Nested pollEvent spikes CPU
« Reply #5 on: June 16, 2015, 01:36:17 am »
Ah ha! I think I have the solution you pointed me to. The code below behaves the same as the code in my original post (as far as I can tell), but without the CPU spike:

#include <SFML/Graphics.hpp>
#include "ResourcePath.hpp"

int main() {
    sf::RenderWindow window(sf::VideoMode(480, 320), "SFML Window");
    window.setFramerateLimit(20);

    sf::Font font;
    if (!font.loadFromFile(resourcePath() + "sansation.ttf")) {
        return 0;
    }
    sf::Text text;
    text.setFont(font);
    text.setCharacterSize(50);
    text.setStyle(sf::Text::Regular);
    text.setColor(sf::Color::Blue);

    while (window.isOpen()) {
        text.setString("Hello SFML");
        window.clear();
        window.draw(text);
        window.display();
       
        bool spacePressed = false;

        sf::Event event;
        while (window.pollEvent(event) || spacePressed == true) {

            if (event.type == sf::Event::Closed) {
                window.close();
                exit(0);
            }

            if (event.type == sf::Event::KeyPressed || spacePressed == true) {
               
                if (event.key.code == sf::Keyboard::Space || spacePressed == true) {
                    spacePressed = true;
                    text.setString("You pressed space");
                    window.clear();
                    window.draw(text);
                    window.display();
                }
               
                if (event.key.code == sf::Keyboard::Escape) {
                    spacePressed = false;
                }
            }
        }
    }
    return 0;
}
 

This code has less "x-mas trees" too (I haven't seen that term before). I'm curious about that. Is the issue with too many "x-mas trees" that it looks ugly and it's easy to make mistakes in, or is there something else that causes this to be an indicator of a problem?

I appreciate all the help. Thank you!

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Nested pollEvent spikes CPU
« Reply #6 on: June 16, 2015, 02:40:16 am »
Try removing both window.clear(), window.draw(), window.display() blocks and put it once after the event loop.

I would suggest removing all of your instances of 'spacePressed == true'. You could add it to the escape key test but it's not really necessary.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*