[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [pygame] Update performance



> Ok. I've spent the last hour or so doing benchmarks of different
> pygame.display.update() techniques. But first the following
> disclaimer:

wowza, i go to sleep one night and look at all this action.
i've been waiting for this topic to come up, so i'd be glad
to hear results from everyone.

> It really, really depends. It depends on what platform you're
> running (windows 2d drivers are almost always better than X11),

i've found this to be pretty true. if you are running on windows
and want to get more of a feel for how linux will handle your
game, force SDL's video driver to use the non-directx code.
in a shell do "set SDL_VIDEODRIVER=windib" and then start the
game in that shell. this will run your game unaccelerated and
performs very comparable to other unix platforms.

it is very important on X to set the video mode to the same
bit depth as the X server is running. There is a small tutorial
in the pygame docs about selecting the fastest video mode. when
you get to the point of speed, getting the video mode set to the
fastest possible will be an important foundation for your game.


> 1) Updating or flipping the whole screen takes a long time

true. you can try to get a video mode with HWACCEL|DOUBLEBUF.
this makes the flipping really fast, but i believe is only supported
under windows directx. :[


> 3) Rect updates are much faster in full-screen mode (with my driver)
> than in windowed mode.

i find this surprising, and will file it in my mental database
for now. the good news is, when most games become "final" they
will always run in fullscreen mode, so this should be a automatic.


> 4) Rect.union() is pretty good. > 
> 5) Something unexpected is going on with overlapping rects. 
> 6) Passing a list of rects to display.update() is very good. 

yes, this is one of the main reasons rect.union exists. you'll
notice in the aliens example, there are always two rects to
clear a sprite and draw the new one. these two are nearly always
overlapping and its worthwhile to get a union of these two without
even checking.

as david found out, it is well worth your time to make only one
call to display.update(). i think the difference is even bigger
on X systems. (less round trips to the server, etc).



> Summary: Do tests on your target platform. Performance varies for many
> reasons. Don't be afraid of large rects, they're unexpectedly
> fast. Rects near to one another can benifit from the rect.union
> function. Overlapping rects are unexpectedly fast. Fullscreen is
> good. Windows drivers are good. Maintain a list of rects, update that
> list, and clear it for the next frame.

good summary. i think the golden rule is, if the background is not
changing each frame, always go with the updaterects. if you do have
a moving background, hmm. try to stick with a lower resolution, the
best option might even be an in-game toggle for the background, and
systems that cannot do hardware updates won't have to.

what i'd really like is to create a small tutorial/faq with help
and ideas for optimizing this game code. if we find commond pitfalls
that are hard to overcome, i'll be planning to implement some helper
routines in the C extensions to get people around these. We'll just
have to wait and see what starts showing up most.

anyways, this is a good topic for further discussion, but i gotta
run out for now. i'll leave you with this one last tip for keeping
python fast.

with a little care, small loops in python can become a lot faster.
i've found this true again and again. it is easy to do and i've
seen code speed up dramatically.

this is for small tight loops (not the main game loop, but loops
inside that). python function and variable lookups can sometimes be
quite slow. but local variables in the function are pretty quick, so
before a loop, it pays to make local variables reference all functions
and variables used inside the loop. also, there is no optimizer like
in C to move dead code outside of loops, so definitely do that yourself.
here is a small example of before and after.

def MoveCreatures(creaturelist):
    "This is the usual and SLOW method of looping"
    for c in creaturelist:
        if c.rect.colliderect(game.data.player.rect):
            c.attack()
        else:
            c.rect.move(CREATURESPEED * game.data.difficulty, 5)
        game.thinkmonster(c)

here is the after version, you would find this runs incredibly faster

def NewMoveCreatures(creaturelist):
    "This has local vars for everthing"
    player_rect = game.data.player.rect
    movement = CREATURESPEED * game.data.difficulty, 5
    think = game.thinkmonster
    for c in creaturelist:
        r = c.rect
        if r.colliderect(player_rect):
            c.attack():
        else:
            r.move(movement)
    think(c)

does this make sense. go ahead and try it for your more intense
loops, i think you'll be surprised. but be careful. remember that
optimizing your code too early in the development can turn into a
nightmare.

there's more to talk about, but the wife is pulling me away :]
goodluck out there.


____________________________________
pygame mailing list
pygame-users@seul.org
http://pygame.seul.org