[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:

It really, really depends. It depends on what platform you're
running (windows 2d drivers are almost always better than X11),
whether you're fullscreen or windowed, what size your blits are,
whether they overlap, whether your surfaces are hardware or software
(again, surfaces under Windows will frequently be hardware accelerated
if they're fullscreen, under X11 they'll nearly always be
software). And of course it really really depends on your
hardware. The conclusions I've drawn are only valid for my combination
of hardware (Voodoo3, 525 Mhz Celeron) and software (XFree 3.3.6). For
example, the Voodoo3 and Matrox G400 are reputed to have excellent
non-accelerated 2d performance. Your mileage may vary.

1) Updating or flipping the whole screen takes a long time. That time
doesn't vary in windowed vs fullscreen modes, but it does increase
linearly with resolution (a 1024 x 768 screen has 2.5 times as many
pixels as a 640 x 480 screen, and takes 2.5 times as long to
update). The amount of time doesn't vary depending on how much drawing
you've done on the display in the meantime. I found that updating the
display surface took me 20 ms at 640 x 480.

2) Updating one rect is quite fast. I tried updating 32x32, 24x24 and
16x16 areas. Updating large rects is quite cheap; A 24x24 rect has
2.25 times as many pixels as a 16x16 rect, but only takes 1.20 times
as long to update.

3) Rect updates are much faster in full-screen mode (with my driver)
than in windowed mode. A 24x24 rect took 400 microseconds (0.400 ms)
to update in windowed mode, but only 240 microseconds in
fullscreen. This is a relief, since I develop in windowed mode
(fullscreen crashes are a pain) and so I can expect better final
performance than I see while developing.

4) Rect.union() is pretty good. It returns a rect that contains all
supplied rects. According to (2) above, updating large rects is
comparatively fast, so if you have a couple of rects that are close to
one another, consider updating the union of those rects. I can't be
more specific here; the payoff will depend greatly on how close the
rects are to one another, and how big they are.

5) Something unexpected is going on with overlapping rects. My time
for updating a single 32x32 rect was 450 microseconds. I created two
such rects so that the second overlapped the first by 50% ((200, 200,
32, 32) and (216, 200, 32, 32)). I expected that updating both rects
seperately would take 900 microseconds. Instead, it took 600, the same
amount of time that resulted from updating the union of the two
rects. From this I conclude that there's some optimization going on
somewhere; that overlapping rects are being detected and combined
behind the scenes. Good stuff.

6) Passing a list of rects to display.update() is very good. Aliens.py
maintains a list called dirtyrects, that rects are appended to during
the frame. At the end of the frame, we do a
display.update(dirtyrects). Ten rects in a list, updated that way,
took half the time that it took me to update ten rects serially.

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.


-- 
David Clark
silenus@telus.net

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