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

Re: [pygame] Pygame games run slowly :(



Before I believe you actually optimized things, how does the timing of your new code compare to the original (timeit is your friend)?

Since your lambdas add additional function call overhead, and the list comprehension adds the cost to build a list, I would not assume this is faster.

-Casey

On Jul 30, 2009, at 8:32 AM, Tyler Laing wrote:

Hi,

Well the first optimization that can be done is to use a lambda function and a list comprehension which performs the for loop at C speed will likely bring a huge benefit:

#we use wrappers because blit and tick only return none, which makes functional programming a bit harder...

f=lambda y: y if y.tick() else y
g=lambda z: z.blit(SCREEN, -CAMERA_X)

particles =[lambda x: f(x) if g(x) else f(x) for x in particles]

Et voila! C-speed execution, O(n) run-time. All it looses is readability, and there's the slight overhead of the two lambda functions... and yes, that else clause is needed in there. Of course for actual production code, I'd assume one would use far more descriptive variables than I did.

This works because lambda functions can use if conditions as their expression, so the syntax for that is: lambda <argument list>: <expression A> if <conditional> else <expression B>

Expression A is executed if the conditional is true, and expression B is executed if the conditional is false. So we use the conditional to perform an action, and that action will naturally return None(iirc about blit and tick), which causes expression B to be performed. Since expr A and B are the same, we just perform the conditional, and then do expr B. Unfortunately Python doesn't optimize that though. And in expr B, we use the same structure again, to return the particle to ensure our list has all of its processed particles. In a real compiler, that if else construction would be eliminated. :/

 Isn't python awesome?

-Tyler

On Thu, Jul 30, 2009 at 6:53 AM, Toni Alatalo <antont@xxxxxxxxxxxxx> wrote:
Toni Alatalo kirjoitti:
As for the slow game in question (http://www.pygame.org/project/ 596/) the game designer does say "Thanks! And yes, framerate is definitely an issue on (dare I say) lower-end computers" runs on this ~1Ghz celeron laptop, and perhaps how on a 1.3Ghz G4 mac, and perhaps even profile out of curiousity

Arderyst seemed like a nice game, tested a little now, will perhaps play more with my son some time later :)

The old celeron laptop was actually a whopping 1.6GHz and the game is choppy there with all the (nice!) gfx options on, it event notes about it.

Ran the py2exed version now and don't have profiling tools at hand so didn't go there yet, but read some of the source after had seen when it gets slow, and it seems to do particles and moving decoration objects so that they are not only written in pure py and iterated in pyindividually for every frame, but there is even a separate blit call for every particle:

in play_level.py ln 849:
def Particle_Tick(particles):
  for particle in particles:
      particle.blit(SCREEN, -CAMERA_X)
      particle.tick()

.. with some logic and movement code in both those methods of the Particle class, and eventually a pygame blit.

same seems to be the case with decorative falling objects, in play_level.py ln 1905
def blit_falling_bg_objs(THISFLIP):
  for fallingbgobj in FALLINGBGOBJARRAY:
     (...)
lrect.center = (fallingbgobj[1] - CAMERA_X + math.sin(fallingbgobj[0])*fallingbgobj[3]*10, fallingbgobj[2])
     SCREEN.blit(lsurf, lrect)

I haven't examined this but have used sprite groups to draw many things with one py call, and would guess that such individual blitting might be a bottleneck. Dunno if using e.g. spritegroups there would actually help. If such blitting is indeed slow, Psyco won't help, didn't test that (yet).

In our project I started to use Lepton for particles to have the movement code in native code, expected pure py to be too slow there.

Also that falling object movement code seems like something you could do with numpy to have it efficiently: when you do same op for a lot of objects, just using individual data (the individual pos and move vel), you can do it with arrays. But the array approach is not perhaps easy at all for a beginning programmer to use. So it is like was said in an earlier thread on this list .. in c or other compiled langs you can write more 'stupid' (no insults meant here!) code and it's still fast enough, whereas for py to be efficient for heavy things you must do it cleverly. Dunno if it will be JITting ala Psyco or easier-than-c(++) compiled langs like shedskin (a py -> c++ generator) or d (a friendlier c++) which will help. Or whether we should indeed use numpy for such stuff.

~Toni

again, stopping these rants and explorations now.



--
Visit my blog at http://oddco.ca/zeroth/zblog