SDL Performance

Hi,

I have made a lot of performance testing with SDL and the results was
(strangely) very poor. One of that just draw 2 images one after another, in
a loop, until you close the SDL window. I’m using the 1280x800 window
resolution. In my test (code below) the frame rate doesn’t exceed 17,8 FPS,
what is a very low frame rate, since most games uses between 30 and 60 FPS
(usually). My computer is a core2 duo, 2GB RAM running Ubuntu 10.04 /
Windows 7. The glxgears runs at 432 ~ 476 FPS, and I can run well some games
like OpenTTD, Battle for Wesnoth, Warcraft III, 0 AD, Mupen64 emulator,
among others. I can’t think that this is the normal performance of SDL since
I have seen many games done with it, and they run very well in my machine
(like OpenTTD and Battle for Wesnoth). This simple test is the minimum I can
expect from SDL to run well, whereas a true game with heavy processing
routines will require much more CPU power (like the OpenTTD simulator game).
Drawing little images within a smaller window results me in a maximum of 76
FPS, but I think it’s normal to redraw big screen parts and get a frame rate
of at least 30 FPS. I have done these tests in another machine, Dual core,
2GB RAM, running Ubuntu 11.04 and the results are even worse (9 FPS, 38 FPS
maximum with little images and low screen/window resolution). I don’t know
if I’m doing something wrong, If anyone have any idea, please help me fix
this performance. I tried to change the SDL_SetVideoMode flags to
SDL_HWSURFACE with no results. The program counts the number of screen flips
(frames) and if you run with

$time ./exec

you can divide the count by the running time yielded, getting the frame rate
in frames per second (FPS).

Here is my code:

#include “SDL/SDL.h”
#include “SDL/SDL_image.h”

int main()
{
// initialize video
if(SDL_Init(SDL_INIT_VIDEO) < 0) exit(1);
SDL_Surface* screen = SDL_SetVideoMode(1280, 800, 16, SDL_SWSURFACE);
if(screen == NULL) exit(1);

bool quit = false;

SDL_Surface** img = new SDL_Surface*[2];
img[0] = IMG_Load("big.png");
img[1] = IMG_Load("big2.png");

int frames = 0;
int index = 0;

while(!quit)
{
    // clear screen
    SDL_Rect rect = {0, 0, 1280, 800 };
    SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 0, 0, 0));

    // draw random image
    index = (index == 0 ? 1 : 0);
    SDL_Rect r = { 0, 0, 0, 0 };
    SDL_BlitSurface(img[index], NULL, screen, &r);

    // flip
    SDL_Flip(screen);

    frames++;

    // check exit
    SDL_Event event;
    while(SDL_PollEvent(&event))
        if(event.type == SDL_QUIT)
        {
            quit = true;
            break;
        }
}

printf("total frames: %d\n", frames);

return 0;

}

Built with:

g++ -o exec main.cpp -lSDL -lSDL_image

The test images are attached, but any PNG with 1280x800 would work.–
Yuri
-------------- next part --------------
A non-text attachment was scrubbed…
Name: big.png
Type: image/png
Size: 23730 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20111015/ce7bbed5/attachment.png
-------------- next part --------------
A non-text attachment was scrubbed…
Name: big2.png
Type: image/png
Size: 23552 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20111015/ce7bbed5/attachment-0001.png

Hi,

I have made a lot of performance testing with SDL and the results was
(strangely) very poor. One of that just draw 2 images one after another, in
a loop, until you close the SDL window. I’m using the 1280x800 window
resolution. In my test (code below) the frame rate doesn’t exceed 17,8 FPS,
what is a very low frame rate, since most games uses between 30 and 60 FPS
(usually). My computer is a core2 duo, 2GB RAM running Ubuntu 10.04 /
Windows 7. The glxgears runs at 432 ~ 476 FPS, and I can run well some games
like OpenTTD, Battle for Wesnoth, Warcraft III, 0 AD, Mupen64 emulator,
among others. I can’t think that this is the normal performance of SDL since
I have seen many games done with it, and they run very well in my machine
(like OpenTTD and Battle for Wesnoth). This simple test is the minimum I can
expect from SDL to run well, whereas a true game with heavy processing
routines will require much more CPU power (like the OpenTTD simulator game).
Drawing little images within a smaller window results me in a maximum of 76
FPS, but I think it’s normal to redraw big screen parts and get a frame rate
of at least 30 FPS. I have done these tests in another machine, Dual core,
2GB RAM, running Ubuntu 11.04 and the results are even worse (9 FPS, 38 FPS
maximum with little images and low screen/window resolution). I don’t know
if I’m doing something wrong, If anyone have any idea, please help me fix
this performance. I tried to change the SDL_SetVideoMode flags to
SDL_HWSURFACE with no results. The program counts the number of screen flips
(frames) and if you run with

$time ./exec

you can divide the count by the running time yielded, getting the frame rate
in frames per second (FPS).

Here is my code:

#include “SDL/SDL.h”
#include “SDL/SDL_image.h”

int main()
{
// initialize video
if(SDL_Init(SDL_INIT_VIDEO) < 0) exit(1);
SDL_Surface* screen = SDL_SetVideoMode(1280, 800, 16, SDL_SWSURFACE);
if(screen == NULL) exit(1);

bool quit = false;

SDL_Surface** img = new SDL_Surface*[2];
img[0] = IMG_Load("big.png");
img[1] = IMG_Load("big2.png");

int frames = 0;
int index = 0;

while(!quit)
{
    // clear screen
    SDL_Rect rect = {0, 0, 1280, 800 };
    SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 0, 0, 0));

    // draw random image
    index = (index == 0 ? 1 : 0);
    SDL_Rect r = { 0, 0, 0, 0 };
    SDL_BlitSurface(img[index], NULL, screen, &r);

    // flip
    SDL_Flip(screen);

    frames++;

    // check exit
    SDL_Event event;
    while(SDL_PollEvent(&event))
        if(event.type == SDL_QUIT)
        {
            quit = true;
            break;
        }
}

printf("total frames: %d\n", frames);

return 0;

}

Built with:

g++ -o exec main.cpp -lSDL -lSDL_image

The test images was attached but I removed them because the message became
too big, but any PNG with 1280x800 would work.–
Yuri

Well, one thing you can do is optimize your surfaces for display with
SDL_DisplayFormat (or SDL_DisplayFormatAlpha if they’ve got alpha).
Something like this:

SDL_Surface *optimize (SDL_Surface *surf)
{
SDL_Surface *opt = SDL_DisplayFormat(surf);
if (opt)
{
SDL_FreeSurface(surf);
return opt;
}
return surf;
}

Just wrap your loads with that:

 img[0] = optimize(IMG_Load("big.png"));
 img[1] = optimize(IMG_Load("big2.png"));

Another thing is that your fps code is a bit inaccurate. It includes
everything like initial setup and loading, so if you don’t run your
example for a long time the framerate will be reported a bit lower than
it really is. Better to calculate it directly:

 Uint32 start = SDL_GetTicks();
 while (!quit) { ... }
 double fps = frames / ((SDL_GetTicks() - start) / 1000.0);

Also, you don’t enable optimization in your compiler invocation.
Optimization probably won’t hurt.

Anyways, if you really want performance, you probably want hardware
acceleration… Hardware-accelerated OpenGL will always be faster than
anything you can do in pure software. You can use it directly, or
indirectly through something like SDL 1.3, for example.

-g

Den 15. okt. 2011 16:18, skrev Yuri David Santos:> Hi,

I have made a lot of performance testing with SDL and the results was
(strangely) very poor. One of that just draw 2 images one after another,
in a loop, until you close the SDL window. I’m using the 1280x800 window
resolution. In my test (code below) the frame rate doesn’t exceed 17,8
FPS, what is a very low frame rate, since most games uses between 30 and
60 FPS (usually). My computer is a core2 duo, 2GB RAM running Ubuntu
10.04 / Windows 7. The glxgears runs at 432 ~ 476 FPS, and I can run
well some games like OpenTTD, Battle for Wesnoth, Warcraft III, 0 AD,
Mupen64 emulator, among others. I can’t think that this is the normal
performance of SDL since I have seen many games done with it, and they
run very well in my machine (like OpenTTD and Battle for Wesnoth). This
simple test is the minimum I can expect from SDL to run well, whereas a
true game with heavy processing routines will require much more CPU
power (like the OpenTTD simulator game). Drawing little images within a
smaller window results me in a maximum of 76 FPS, but I think it’s
normal to redraw big screen parts and get a frame rate of at least 30
FPS. I have done these tests in another machine, Dual core, 2GB RAM,
running Ubuntu 11.04 and the results are even worse (9 FPS, 38 FPS
maximum with little images and low screen/window resolution). I don’t
know if I’m doing something wrong, If anyone have any idea, please help
me fix this performance. I tried to change the SDL_SetVideoMode flags to
SDL_HWSURFACE with no results. The program counts the number of screen
flips (frames) and if you run with

$time ./exec

you can divide the count by the running time yielded, getting the frame
rate in frames per second (FPS).

Here is my code:

#include “SDL/SDL.h”
#include “SDL/SDL_image.h”

int main()
{
// initialize video
if(SDL_Init(SDL_INIT_VIDEO) < 0) exit(1);
SDL_Surface* screen = SDL_SetVideoMode(1280, 800, 16, SDL_SWSURFACE);
if(screen == NULL) exit(1);

 bool quit = false;

 SDL_Surface** img = new SDL_Surface*[2];
 img[0] = IMG_Load("big.png");
 img[1] = IMG_Load("big2.png");

 int frames = 0;
 int index = 0;

 while(!quit)
 {
     // clear screen
     SDL_Rect rect = {0, 0, 1280, 800 };
     SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 0, 0, 0));

     // draw random image
     index = (index == 0 ? 1 : 0);
     SDL_Rect r = { 0, 0, 0, 0 };
     SDL_BlitSurface(img[index], NULL, screen, &r);

     // flip
     SDL_Flip(screen);

     frames++;

     // check exit
     SDL_Event event;
     while(SDL_PollEvent(&event))
         if(event.type == SDL_QUIT)
         {
             quit = true;
             break;
         }
 }

 printf("total frames: %d\n", frames);

 return 0;

}

Built with:

g++ -o exec main.cpp -lSDL -lSDL_image

The test images was attached but I removed them because the message
became too big, but any PNG with 1280x800 would work.


Yuri


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

(The short answer is: this is the wrong way to do this. But if you
really want to do this with software surfaces, there is still room for
improvement.)

int main()
{
// initialize video
if(SDL_Init(SDL_INIT_VIDEO) < 0) exit(1);
SDL_Surface* screen = SDL_SetVideoMode(1280, 800, 16, SDL_SWSURFACE);

Did you actually want a 16-bit surface? It’s likely that you’re not able
to get this from the OS, so SDL is converting all your pixels on the
fly…so you draw everything twice…once to the surface, and then again
when SDL converts it to the format the OS wants.

Specifying 0 (“take whatever the OS gives me by default”) there may help
here, since you don’t actually require an array of 16-bit pixels for
your work in this case.

 SDL_Surface** img = new SDL_Surface*[2];
 img[0] = IMG_Load("big.png");
 img[1] = IMG_Load("big2.png");

Convert these surfaces to the screen format. Otherwise, every blit isn’t
a copy, but a possibly-expensive conversion. SDL_ConvertSurface()
handles that.

     SDL_Rect rect = {0, 0, 1280, 800 };
     SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 0, 0, 0));

Use a NULL instead of &rect. Some systems can (theoretically) optimize
for clearing the whole surface this way. Also, if you’re just going to
draw over the entire surface with a 1280x800 png, don’t clear it at all.
All you’re doing is drawing to pixels you’re about to write over again
anyhow.

The test images was attached but I removed them because the message
became too big, but any PNG with 1280x800 would work.

Doing a software blit of a 1280x800 image is going to be slow in any
case. The successful examples you listed are either using OpenGL, or
they’re not redrawing the whole screen every frame.

Use OpenGL, upload those PNGs to a textures once, and draw a textured
quad each frame, and it’ll run at thousands of frames per second.

–ryan.

Hi,

Gerry and Ryan, thank you for the tips, you solved my problem. I did the
same tests, now using the SDL_ANYFORMAT flag and specifying 0 in the
bit-dept parameter, and optimizing the surfaces with the
SDL_DisplayFormatAlpha. The results was outstanding!

  • With only the SDL_SetVideoMode modifications the performance improved from
    about 17 FPS to 30 FPS.
  • With only the SDL_DisplayFormatAlpha modification it improved from 17 to
    33 FPS.
  • And with both, it improved to amazing 97,28 FPS.
  • Tests with little images exceeded 360 FPS, without OpenGL.

I know my timing method is not so accurate, but running the test for more
than 20 seconds it gives a good average measure.

Thanks!
Problem solved!

2011/10/15 Ryan C. Gordon >

(The short answer is: this is the wrong way to do this. But if you really
want to do this with software surfaces, there is still room for
improvement.)

int main()

{
// initialize video
if(SDL_Init(SDL_INIT_VIDEO) < 0) exit(1);
SDL_Surface* screen = SDL_SetVideoMode(1280, 800, 16, SDL_SWSURFACE);

Did you actually want a 16-bit surface? It’s likely that you’re not able to
get this from the OS, so SDL is converting all your pixels on the fly…so
you draw everything twice…once to the surface, and then again when SDL
converts it to the format the OS wants.

Specifying 0 (“take whatever the OS gives me by default”) there may help
here, since you don’t actually require an array of 16-bit pixels for your
work in this case.

 SDL_Surface** img = new SDL_Surface*[2];
img[0] = IMG_Load("big.png");
img[1] = IMG_Load("big2.png");

Convert these surfaces to the screen format. Otherwise, every blit isn’t a
copy, but a possibly-expensive conversion. SDL_ConvertSurface() handles
that.

     SDL_Rect rect = {0, 0, 1280, 800 };
    SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 0, 0, 0));

Use a NULL instead of &rect. Some systems can (theoretically) optimize for
clearing the whole surface this way. Also, if you’re just going to draw over
the entire surface with a 1280x800 png, don’t clear it at all. All you’re
doing is drawing to pixels you’re about to write over again anyhow.

The test images was attached but I removed them because the message

became too big, but any PNG with 1280x800 would work.

Doing a software blit of a 1280x800 image is going to be slow in any case.
The successful examples you listed are either using OpenGL, or they’re not
redrawing the whole screen every frame.

Use OpenGL, upload those PNGs to a textures once, and draw a textured quad
each frame, and it’ll run at thousands of frames per second.

–ryan.

_____________**
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/**listinfo.cgi/sdl-libsdl.orghttp://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


Yuri David Santos
Aleva - Solu??es em Software
www.aleva.com.br

What version of SDL are you running? This performance may have been
addressed in a different version/repository revision.
Otherwise, software surfaces can be slow, whereas OpenGL uses hardware
acceleration. Also, it would be good to know what your monitor’s native
resolution is, and what sort of frame rate you get with the games you
listed (and what their respective resolutions are).
-AlexOn Sat, Oct 15, 2011 at 2:18 AM, Yuri David Santos < yuridavidsantos at gmail.com> wrote:

Hi,

I have made a lot of performance testing with SDL and the results was
(strangely) very poor. One of that just draw 2 images one after another, in
a loop, until you close the SDL window. I’m using the 1280x800 window
resolution. In my test (code below) the frame rate doesn’t exceed 17,8 FPS,
what is a very low frame rate, since most games uses between 30 and 60 FPS
(usually). My computer is a core2 duo, 2GB RAM running Ubuntu 10.04 /
Windows 7. The glxgears runs at 432 ~ 476 FPS, and I can run well some
games like OpenTTD, Battle for Wesnoth, Warcraft III, 0 AD, Mupen64
emulator, among others. I can’t think that this is the normal performance
of SDL since I have seen many games done with it, and they run very well in
my machine (like OpenTTD and Battle for Wesnoth). This simple test is the
minimum I can expect from SDL to run well, whereas a true game with heavy
processing routines will require much more CPU power (like the OpenTTD
simulator game). Drawing little images within a smaller window results me
in a maximum of 76 FPS, but I think it’s normal to redraw big screen parts
and get a frame rate of at least 30 FPS. I have done these tests in another
machine, Dual core, 2GB RAM, running Ubuntu 11.04 and the results are even
worse (9 FPS, 38 FPS maximum with little images and low screen/window
resolution). I don’t know if I’m doing something wrong, If anyone have any
idea, please help me fix this performance. I tried to change the
SDL_SetVideoMode flags to SDL_HWSURFACE with no results. The program counts
the number of screen flips (frames) and if you run with

$time ./exec

you can divide the count by the running time yielded, getting the frame
rate in frames per second (FPS).

Here is my code:

#include “SDL/SDL.h”
#include “SDL/SDL_image.h”

int main()
{
// initialize video
if(SDL_Init(SDL_INIT_VIDEO) < 0) exit(1);
SDL_Surface* screen = SDL_SetVideoMode(1280, 800, 16, SDL_SWSURFACE);
if(screen == NULL) exit(1);

bool quit = false;

SDL_Surface** img = new SDL_Surface*[2];
img[0] = IMG_Load("big.png");
img[1] = IMG_Load("big2.png");

int frames = 0;
int index = 0;

while(!quit)
{
    // clear screen
    SDL_Rect rect = {0, 0, 1280, 800 };
    SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 0, 0, 0));

    // draw random image
    index = (index == 0 ? 1 : 0);
    SDL_Rect r = { 0, 0, 0, 0 };
    SDL_BlitSurface(img[index], NULL, screen, &r);

    // flip
    SDL_Flip(screen);

    frames++;

    // check exit
    SDL_Event event;
    while(SDL_PollEvent(&event))
        if(event.type == SDL_QUIT)
        {
            quit = true;
            break;
        }
}

printf("total frames: %d\n", frames);

return 0;

}

Built with:

g++ -o exec main.cpp -lSDL -lSDL_image

The test images are attached, but any PNG with 1280x800 would work.


Yuri


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Like Alex said, you can’t expect software rendering to go fast when redrawing large images. Use OpenGL if you want good performance for redrawing large areas. I’m using OpenGL with SDL 1.3 and can easily get 300+ fps for a large window when the scene is a simpler scene.

Out of curiosity, does IMG_Load() format the surface to the screen’s
format as well ? I can’t recall if it does or not :confused:

if not - that’d be part of the slow down and would need
SDL_DisplayFormat after it’s loaded.

-WillOn 10/15/2011 1:18 AM, Yuri David Santos wrote:

Hi,

I have made a lot of performance testing with SDL and the results was
(strangely) very poor. One of that just draw 2 images one after
another, in a loop, until you close the SDL window. I’m using the
1280x800 window resolution. In my test (code below) the frame rate
doesn’t exceed 17,8 FPS, what is a very low frame rate, since most games

Out of curiosity, does IMG_Load() format the surface to the screen’s
format as well ?

No, you’d have to convert.

(This is a thread from October 15th that popped up again today for some
reason:
http://lists.libsdl.org/pipermail/sdl-libsdl.org/2011-October/082495.html )

–ryan.

My understanding is that it does not and you have to do the conversion.

If I’m not wrong, you may have hit the nail on the head.

To the OP (Yuri) - can you convert the image surface to your display
surface format outside the loop and see if there’s any improvement?

-Vijay

Hi,

I have made a lot of performance testing with SDL and the results was
(strangely) very poor. One of that just draw 2 images one after
another, in a loop, until you close the SDL window. I’m using the
1280x800 window resolution. In my test (code below) the frame rate
doesn’t exceed 17,8 FPS, what is a very low frame rate, since most
gamesOn Tue, 08 Nov 2011 13:24:28 -0600, William Langford wrote:
On 10/15/2011 1:18 AM, Yuri David Santos wrote:

Out of curiosity, does IMG_Load() format the surface to the screen’s
format as well ? I can’t recall if it does or not :confused:

if not - that’d be part of the slow down and would need
SDL_DisplayFormat after it’s loaded.

-Will


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Vijay Varadan
Skype: vijayvaradan | USA: +1-206-849-3710 ©
India: +1-425-956-3326 (VOIP) | India: +91-99400-13652 ©
LinkedIn: http://linkd.in/qTORH7 | Blog: http://bit.ly/oQBwNl
Google+: http://bit.ly/vijayplus | Facebook: http://on.fb.me/oF7dq9
Twitter: http://bit.ly/qsiqrp

AXHAM CORPORATION | Axham Technologies, LLP
LinkedIn: http://linkd.in/nL9wNX | LinkedIn: http://linkd.in/odgEc9
Website: http://axham.com | Facebook: http://on.fb.me/axhamgames
Twitter: http://bit.ly/mPaDwB