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 <ant...@kyperjokki.fi>
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