[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] blit speedup



On Mar 28, 2010, at 12:24 PM, Wakefield, Robert wrote:

> I've made a tiling engine where tiles are stored as list of subsurfaces from a texture surface, and the game map is stored as a list of tile indices.  The problem is that I'm ending up with some slowdown even at low resolutions.  I was wondering if anyone's run into this before and could offer suggestions.  The code I have in the map draw() function is:
> 
>    for i in self.tiledata: # i is an integer, tiledata is a standard list right now, will convert to an array for speed as the next step
>        surf = dat[i]
>        sys.screen.blit(surf, (i, i)) # I would use real coordinates, the i, i is just for speed testing
> 
> In particular:
>    (a.) is there a way to speed up surface.blit()?  I've already used surface.convert(), and from some of the tutorials hardware surfaces sound problematic.
>    (b.) Is there a way to call the blit function from inlined C code?  I've seen the SciPy.blitz examples showing a massive speedup on similar loops by doing this.

Before worrying about specific optimizations you should profile (run with `python -m cProfile` etc). If you have already identified that blitting is the most expensive thing, then speeding up the things around it (using arrays instead of lists, which btw may not be faster at all), or moving the loop itself into C will only help you a little.

One approach I like to take is to look at the thing you plan to optimize and measure how much of the time is being spent there. Then compare the total time begin spent on everything to the total time that would be spent on everything if you could reduce the cost of the optimization target to zero. Sometimes the savings, even with infinite optimization, is not worth the bother.

So if blit is truly your bottleneck, and that would not be entirely surprising, your choices are:

1. Make each individual blit faster
2. Do fewer blits (ideally zero ;^)

You only have so much ability to affect #1. This involves lining up the stars so that each blit does as little work as possible. Angles of attack here include things mentioned like hardware surfaces, resolution, convert(). Also individual surface size is a big factor (bigger or smaller could be faster). Also, are you running full-screen or in a window? That can make a big performance difference. What about screen color depth? What about alpha blending? less is more here.

You have more direct control over #2. Maybe you can use scroll instead of blit, then clean up and parts where foreground objects are? Maybe you can use bigger tile surfaces, or etc.

In my experience for games where the entire screen must be redrawn each frame (e.g. many scrollers) pygame's cpu blitting is often not fast enough. You may want to consider using OpenGL, or and OpenGL-based tile engine to get the performance you want.

-Casey