SDL_WaitEventTimeout CPU usage on Raspberry PI [solved]

Hi all.

There’s another recent similar topic but I’m in a slightly different situation, so I think I should open a new thread. Hope you don’t mind.

I’m writing a small demo program using SDL2 and cairo, just to get acquaintance with SDL2. Open a window, load a BMP, draw a line, all good so far.

My event loop is this:

   while (1) {                                                                                                              
      rc = SDL_WaitEventTimeout(&event, 3000);                                                                                    
      if (rc == 0) {                                                                                                              
        printf("timeout? %s\n", SDL_GetError());                                                                                  
      printf("event type: %d\n", event.type);                                                                                     
      if (event.type == SDL_QUIT) {                                                                                               

On my Ubuntu 18.04 laptop, SDL2 version 2.0.8, the CPU usage of my process is, as expected, almost 0.
But on Raspberry PI 2, running Raspbian with its system-provided SDL2 version 2.0.5, plain X11 with no desktop environment, I get a 20% CPU usage. There’s clearly something wrong. But… what?

Thanks for any suggestion.

P.S.: There’s a place in this forum dedicated to SDL on Raspberry PI?

20% CPU usage from your program or 20% overall? 20% of one core or 20% of all cores?
Does it get lower if you remove the printf()? (ok, with 3sec timeout that’s probably not significant)

One thing to keep in mind is that a Desktop CPU is a lot faster than RPi’s CPU, so the same amount of work causes a higher percentage of CPU load…
(20% still seems a bit high)

20% for my process alone (on one core, this is a single threaded program). It is VERY high, even on the low power RPi processor. A single printf every 3 seconds is negligible as CPU usage. I’d probably be suspicious even for a 2% of usage.

Hmm so SDL_WaitEventTimeout() calls SDL_Delay(10) between checking for new events, and SDL_Delay() calls the system’s nanosleep() function.
I don’t know how exactly nanosleep() is implemented, but it seems likely that it uses CPU-specific instructions (if available). So maybe x86(_64) has instructions that allow sleeping for a few milliseconds without causing load, and ARM doesn’t (or at least none that are as good)?
You could try a simple C program to see how “costly” nanosleep() for 10ms is, like

#include <time.h>
int main(int argc, char** argv)
	struct timespec tenMs;
	tenMs.tv_sec = 0;
	tenMs.tv_nsec = 10000000l; // 10ms in ns ; UPDATE: fixed typo here
	while(1) {
		nanosleep(&tenMs, NULL);
	return 0;

I ran your code on my RPi and its cpu usage is barely visible in top. So nanosleep() is fine.
But you have an interesting point. What else does SDL_WaitEventTimeout() in its loop?

Anybody can look at the source, but to save you the trouble here’s what it is in 2.0.5:

int SDL_WaitEventTimeout(SDL_Event * event, int timeout)
    Uint32 expiration = 0;

    if (timeout > 0)
        expiration = SDL_GetTicks() + timeout;

    for (;;) {
        switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
        case -1:
            return 0;
        case 0:
            if (timeout == 0) {
                /* Polling and no events, just return */
                return 0;
            if (timeout > 0 && SDL_TICKS_PASSED(SDL_GetTicks(), expiration)) {
                /* Timeout expired and no events */
                return 0;
            /* Has events */
            return 1;

Thank you.

Now I’m having troubles recompiling a working SDL for RPi, in order to do the profiling of that loop. I can’t find, right now, how the system-provided library was compiled. But this isn’t matter for this thread.

Couldn’t you simply copy that function into your own program (change its name of course!) and profile it there?

I didn’t thought about it… that’s a clever idea :slight_smile: I focused on recompiling SDL because I also want to update it, but in the meantime I can do as you say to work on this problem.


I made some rough profiling on the loop.

SDL_PumpEvents() takes, on the Raspberry Pi, 6.5 milliseconds to return; compared to the 10ms delay inside the loop, it is pretty big. Given the purpose of this function, there’s a change the problem lives outside SDL.

I’ll try to dig a little bit inside of it.

yeah, that would’ve been my next guess - if nanosleep() indeed sleeps and keeps CPU usage low, it must be SDL_PumpEvents() and whatever it calls - I guess to debug/profile that further you’ll have to build SDL yourself after all - and if you’re very lucky the problem might have been fixed at some point between 2.0.5 and 2.0.9 (or current HG) :wink:

There’s a way to know the configure options that were used to compile the system provided SDL library?

Generally not, I think - but you should be able to get the package source from your Linux distro and figure out what they’re using. apt-get source libsdl2-2.0-0 should download the source (if you have apt repos for sources configured) and extract it and set up the debian (or Raspbian) specific patches etc.
There will be a debian/ directory in that extracted source directory then, look around there for information; especially debian/rules is interesting (it’s the makefile to build the .deb), but debian/control is as well, it lists the build dependencies. Speaking of build dependencies, apt-get build-dep libsdl2-2.0-0 should install all of those, I guess that’d help as well?

Hi all.

I was able to solve this problem recompiling SDL 2.0.9 without some things I don’t need:

./configure --disable-dbus --disable-ime --disable-ibus --disable-audio --host=arm-raspberry-linux-gnueabihf

I can’t tell if the bug has been solved moving from SDL 2.0.5 to 2.0.9 or has been excluded by the disabled features.
Now I have another problem, still only on the Raspberry PI, when this function returns due to the timeout expiration. But I think this is matter for another thread.

Thank you all.