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

Re: [pygame] blit speedup



hi,

If you just want to make a game, rather than an engine/library, it
might be better to just go with pygame Surfaces.  But if messing
around with engines, and opengl is more your idea of fun...

There's a number of threads on the mailing list about making a fast
tiling engine.


On Sun, Mar 28, 2010 at 11:29 PM, Wakefield, Robert
<rjw03002@xxxxxxxxxxxxxx> wrote:
> Do you have any recommendation for the best way to get an OpenGL engine running, especially going Pygame surface to OpenGL texture?  I'd like to preserve platform-independent .py files or executables if possible.
>
> I had previously coded a simple engine with OpenGL/C++, and trying to get textures from LibPNG or the like proved to be a headache even on different machines, let alone a separate OS.
>
> As a side note regarding profiling, I had code profiled previously and had been trying to optimize the loop based on that, but the results were misleading.  The profiler said I had spend ~1.3 of 5 seconds in the loop function and the rest in blit(), but I copied the loop function else without the blit and its profile usage went down to ~0.3s.
>
> So the message is to check twice when you're profiling ;)  At least I know the problem is definitely blit().
> ________________________________________
> From: owner-pygame-users@xxxxxxxx [owner-pygame-users@xxxxxxxx] On Behalf Of Casey Duncan [casey@xxxxxxxxxxx]
> Sent: Sunday, March 28, 2010 3:13 PM
> To: pygame-users@xxxxxxxx
> Subject: 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
>