Last active
January 4, 2019 10:28
-
-
Save illume/41a065bf92201330666b7d8a20a634ca to your computer and use it in GitHub Desktop.
pypy hacky benchmark based on example testsprite.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# like the testsprite.c that comes with sdl, this pygame version shows | |
# lots of sprites moving around. | |
import pygame, sys, os | |
from pygame.locals import * | |
from random import randint | |
from time import time | |
import gc | |
import pygame.joystick | |
from pygame.compat import xrange_ | |
##import FastRenderGroup as FRG | |
import pygame.sprite as FRG | |
if "-psyco" in sys.argv: | |
try: | |
import psyco | |
psyco.full() | |
except Exception: | |
print ("No psyco for you! psyco failed to import and run.") | |
jit_on = True | |
try: | |
import pypyjit | |
except: | |
pass | |
jit_on = False | |
main_dir = os.path.split(os.path.abspath(__file__))[0] | |
data_dir = os.path.join(main_dir, 'data') | |
from Queue import Queue | |
from threading import Event, Thread | |
import pygame | |
# def gc_collect_step(q): | |
# """ this calls the gc in a thread. | |
# """ | |
# while True: | |
# # print '5) GC THREAD: Waiting to do gc.' | |
# ready_to_go = q.get() | |
# # print '4) GC THREAD: calling gc_collect_step' | |
# if hasattr(gc, "collect_step"): | |
# gc.collect_step() | |
# q.task_done() | |
# gc_queue = Queue() | |
# worker = Thread(target=gc_collect_step, args=(gc_queue,)) | |
from Queue import Queue | |
from threading import Event, Thread, Lock | |
import pygame | |
def gc_collect_step(event): | |
""" this calls the gc in a thread. | |
""" | |
while True: | |
print '5) GC THREAD: Waiting to do gc.' | |
event.wait() | |
print '4) GC THREAD: calling gc_collect_step' | |
if hasattr(gc, "collect_step"): | |
gc.collect_step() | |
event.clear() | |
gc_event = Event() | |
worker = Thread(target=gc_collect_step, args=(gc_event,)) | |
worker.setDaemon(True) | |
worker.start() | |
# pygame.display.set_mode((640, 480)) | |
# clock = pygame.time.Clock() | |
# while True: | |
# print('1) at top of loop') | |
# pygame.event.get() | |
# gc_event.set() | |
# print('2) tell GC thread to collect') | |
# print('3) flipping display. GIL released') | |
# pygame.display.flip() | |
# print ('6) finished flipping. GIL grabbed') | |
# clock.tick() | |
# print(clock.get_fps()) | |
# use this to use update rects or not. | |
# If the screen is mostly full, then update rects are not useful. | |
update_rects = True | |
if "-update_rects" in sys.argv: | |
update_rects = True | |
if "-noupdate_rects" in sys.argv: | |
update_rects = False | |
use_static = False | |
if "-static" in sys.argv: | |
use_static = True | |
use_FastRenderGroup = False | |
if "-FastRenderGroup" in sys.argv: | |
update_rects = True | |
use_FastRenderGroup = True | |
flags = 0 | |
if "-flip" in sys.argv: | |
flags ^= DOUBLEBUF | |
if "-fullscreen" in sys.argv: | |
flags ^= FULLSCREEN | |
if "-sw" in sys.argv: | |
flags ^= SWSURFACE | |
use_rle = True | |
if "-hw" in sys.argv: | |
flags ^= HWSURFACE | |
use_rle = False | |
screen_dims = [640, 480] | |
if "-height" in sys.argv: | |
i = sys.argv.index("-height") | |
screen_dims[1] = int(sys.argv[i+1]) | |
if "-width" in sys.argv: | |
i = sys.argv.index("-width") | |
screen_dims[0] = int(sys.argv[i+1]) | |
if "-alpha" in sys.argv: | |
use_alpha = True | |
else: | |
use_alpha = False | |
plot = '-plot' in sys.argv | |
print (screen_dims) | |
##class Thingy(pygame.sprite.Sprite): | |
## images = None | |
## def __init__(self): | |
## pygame.sprite.Sprite.__init__(self) | |
## self.image = Thingy.images[0] | |
## self.rect = self.image.get_rect() | |
## self.rect.x = randint(0, screen_dims[0]) | |
## self.rect.y = randint(0, screen_dims[1]) | |
## #self.vel = [randint(-10, 10), randint(-10, 10)] | |
## self.vel = [randint(-1, 1), randint(-1, 1)] | |
## | |
## def move(self): | |
## for i in [0, 1]: | |
## nv = self.rect[i] + self.vel[i] | |
## if nv >= screen_dims[i] or nv < 0: | |
## self.vel[i] = -self.vel[i] | |
## nv = self.rect[i] + self.vel[i] | |
## self.rect[i] = nv | |
class Thingy(FRG.DirtySprite): | |
images = None | |
def __init__(self): | |
## pygame.sprite.Sprite.__init__(self) | |
FRG.DirtySprite.__init__(self) | |
self.image = Thingy.images[0] | |
self.rect = self.image.get_rect() | |
self.rect.x = randint(0, screen_dims[0]) | |
self.rect.y = randint(0, screen_dims[1]) | |
#self.vel = [randint(-10, 10), randint(-10, 10)] | |
self.vel = [randint(-1, 1), randint(-1, 1)] | |
self.dirty = 2 | |
def update(self): | |
for i in [0, 1]: | |
nv = self.rect[i] + self.vel[i] | |
if nv >= screen_dims[i] or nv < 0: | |
self.vel[i] = -self.vel[i] | |
nv = self.rect[i] + self.vel[i] | |
self.rect[i] = nv | |
class Static(FRG.DirtySprite): | |
images = None | |
def __init__(self): | |
FRG.DirtySprite.__init__(self) | |
self.image = Static.images[0] | |
self.rect = self.image.get_rect() | |
self.rect.x = randint(0, 3*screen_dims[0]/4) | |
self.rect.y = randint(0, 3*screen_dims[1]/4) | |
def main(update_rects = True, | |
use_static = False, | |
use_FastRenderGroup = False, | |
screen_dims = [640, 480], | |
use_alpha = False, | |
flags = 0, | |
plot = False): | |
"""Show lots of sprites moving around | |
Optional keyword arguments: | |
update_rects - use the RenderUpdate sprite group class (default True) | |
use_static - include non-moving images (default False) | |
use_FastRenderGroup - Use the FastRenderGroup sprite group (default False) | |
screen_dims - Pygame window dimensions (default [640, 480]) | |
use_alpha - use alpha blending (default False) | |
flags - additional display mode flags (default no addiontal flags) | |
""" | |
global jit_on | |
if use_FastRenderGroup: | |
update_rects = True | |
#pygame.init() | |
pygame.display.init() | |
#if "-fast" in sys.argv: | |
screen = pygame.display.set_mode(screen_dims, flags) | |
# this is mainly for GP2X, so it can quit. | |
pygame.joystick.init() | |
num_joysticks = pygame.joystick.get_count() | |
if num_joysticks > 0: | |
stick = pygame.joystick.Joystick(0) | |
stick.init() # now we will receive events for the joystick | |
screen.fill([0,0,0]) | |
pygame.display.flip() | |
sprite_surface = pygame.image.load(os.path.join(data_dir, "asprite.bmp")) | |
sprite_surface2 = pygame.image.load(os.path.join(data_dir, "static.png")) | |
if use_rle: | |
sprite_surface.set_colorkey([0xFF, 0xFF, 0xFF], SRCCOLORKEY|RLEACCEL) | |
sprite_surface2.set_colorkey([0xFF, 0xFF, 0xFF], SRCCOLORKEY|RLEACCEL) | |
else: | |
sprite_surface.set_colorkey([0xFF, 0xFF, 0xFF], SRCCOLORKEY) | |
sprite_surface2.set_colorkey([0xFF, 0xFF, 0xFF], SRCCOLORKEY) | |
if use_alpha: | |
sprite_surface = sprite_surface.convert_alpha() | |
sprite_surface2 = sprite_surface2.convert_alpha() | |
else: | |
sprite_surface = sprite_surface.convert() | |
sprite_surface2 = sprite_surface2.convert() | |
Thingy.images = [sprite_surface] | |
if use_static: | |
Static.images = [sprite_surface2] | |
if len(sys.argv) > 1: | |
try: | |
numsprites = int(sys.argv[-1]) | |
except Exception: | |
numsprites = 100 | |
else: | |
numsprites = 100 | |
sprites = None | |
if use_FastRenderGroup: | |
## sprites = FRG.FastRenderGroup() | |
sprites = FRG.LayeredDirty() | |
else: | |
if update_rects: | |
sprites = pygame.sprite.RenderUpdates() | |
else: | |
sprites = pygame.sprite.Group() | |
for i in xrange_(0, numsprites): | |
if use_static and i%2==0: | |
sprites.add(Static()) | |
sprites.add(Thingy()) | |
done = False | |
frames = 0 | |
start = time() | |
background = pygame.Surface(screen.get_size()) | |
background = background.convert() | |
background.fill([0,0,0]) | |
frame_times = [] | |
gc.disable() | |
frames_since_last_gc = 0 | |
while not done: | |
# print('1) at top of loop') | |
t0 = time() | |
for event in pygame.event.get(): | |
if event.type in [KEYDOWN, QUIT, JOYBUTTONDOWN]: | |
done = True | |
if not update_rects: | |
screen.fill([0,0,0]) | |
## for sprite in sprites: | |
## sprite.move() | |
if update_rects: | |
sprites.clear(screen, background) | |
sprites.update() | |
rects = sprites.draw(screen) | |
t1 = time() | |
# print (t1-t0) | |
# gc.collect(0) | |
if t1 - t0 > 0.011: | |
print('slow') | |
# print('frame') | |
# if (t1-t0 < 0.0011 and frames_since_last_gc > 30): | |
# print('2) tell GC thread to collect') | |
# gc_queue.put(True) | |
gc_event.set() | |
# gc.collect_step() | |
# if frames_since_last_gc > 0: | |
# # print('collecting') | |
# frames_since_last_gc = 0 | |
# # gc.collect(0) | |
# # gc.collect_step() | |
# print('put on queue') | |
# gc_queue.put(True) | |
# else: | |
# frames_since_last_gc += 1 | |
# print ('3) flipping display. GIL released') | |
if update_rects: | |
pygame.display.update(rects) | |
else: | |
pygame.display.flip() | |
# print ('6) finished flipping. GIL grabbed') | |
# frame_times.append(time() - t0) | |
frame_times.append(t1 - t0) | |
if jit_on and time() - start > 10: | |
# print('turning off pypyjit') | |
# pypyjit.set_param("off") | |
jit_on = 0 | |
frames += 1 | |
end = time() | |
print ("FPS: %f" % (frames / ((end - start)))) | |
pygame.quit() | |
if plot: | |
msg = '\n'.join(('update_rects:%s,', | |
'use_static:%s,', | |
'use_FastRenderGroup:%s', | |
'screen_dims:%s,', | |
'use_alpha:%s,', | |
'flags: %s')) % ( | |
update_rects, | |
use_static, | |
use_FastRenderGroup, | |
screen_dims, | |
use_alpha, | |
flags | |
) | |
print(msg) | |
import pickle | |
with open('spriteplot.pickle', 'wb') as picklef: | |
pickle.dump({'msg': msg, 'frame_times': frame_times}, picklef) | |
if __name__ == "__main__": | |
if '-plotpickle' in sys.argv: | |
import pickle | |
with open('spriteplot.pickle', 'rb') as picklef: | |
data = pickle.load(picklef) | |
print(data['msg']) | |
import matplotlib.pyplot as plt | |
print(len(data['frame_times'])) | |
plt.plot(data['frame_times'][:1200]) | |
plt.plot(data['frame_times'][-1200:]) | |
# n, bins, patches = plt.hist(data['frame_times'], 50, normed=1, facecolor='g', alpha=0.75) | |
# plt.ylabel('per frame time. pypy gc.disable(), pypyjit.set_param("off") after 10s') | |
# plt.ylabel('30fps. pypy, 1000 sprites') | |
# plt.ylabel('30fps. python36, 1000 sprites, gc.disable()') | |
# plt.ylabel('30fps. pypy, 1000 sprites, gc.disable()') | |
# plt.ylabel('python3.6, 100 sprites. gc.disable()') | |
# plt.ylabel('pypy 6.1.0-alpha0 0679f7b21b79, 100 sprites. gc.disable()') | |
# plt.ylabel('pypy 6.1.0, 1000 sprites. PYPY_GC_NURSERY=1m gc.collect_step()') | |
# plt.ylabel('pypy 6.1.0, 1000 sprites. gc.collect_step()') | |
# plt.ylabel('pypy 6.1.0, 1000 sprites. 42.4FPS gc.disable() gc.collect_step()') | |
plt.ylabel('pypy 6.1.0, 1000 sprites. 47.5 FPS. thread gc.collect_step()') | |
# plt.ylabel('pypy 6.0.0, 1000 sprites. 43FPS.') | |
# plt.ylabel('pypy 6.0.0, 1000 sprites. 31FPS. gc.disable()') | |
# plt.ylabel('python 2.7, 1000 sprites 51FPS.') | |
# plt.ylabel('python 2.7, 300 sprites. gc.disable()') | |
# plt.ylabel('Time per frame, python3.6, gc.disable()') | |
# plt.ylabel('Time per frame, python3.6, gc.disable()') | |
plt.show() | |
else: | |
main(update_rects, | |
use_static, | |
use_FastRenderGroup, | |
screen_dims, | |
use_alpha, | |
flags, | |
plot) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment