The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
SDL Performance
Yuri David Santos
Guest

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 Performance
Gerry Jo Jellestad
Guest

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:
Quote:
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

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

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
SDL Performance
Ryan C. Gordon
Guest

(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.)

Quote:
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.

Quote:
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.

Quote:
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.

Quote:
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

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
SDL Performance
Yuri David Santos
Guest

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
Quote:

(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.)

Quote:
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.

Quote:
    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.

Quote:
        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.

Quote:
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

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org





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