Improved performance by replacing the 'threading', 'socket' and 'Queue' modules with gevent's more efficient modules.

This commit is contained in:
CodePanter 2016-03-11 20:15:24 +01:00
parent c5272c6439
commit df73d17c44

View file

@ -5,36 +5,38 @@ Inspired by the PixelFlut beamer on eth0:winter 2016 and
code from https://github.com/defnull/pixelflut/ code from https://github.com/defnull/pixelflut/
""" """
__version__ = 0.1 __version__ = 0.2
__author__ = "Jan Klopper <jan@underdark.nl>" __author__ = "Jan Klopper <jan@underdark.nl>"
import pygame import pygame
import socket
import struct import struct
import Queue
import threading
import time import time
from gevent import spawn, socket, monkey
from gevent.server import DatagramServer
from gevent.queue import Queue
monkey.patch_all()
UDP_IP = "127.0.0.1"
UDP_PORT= 5005
def main(): def main():
"""Runs a pixelvloed server""" """Runs a pixelvloed server"""
PixelVloed() PixelVloed(':%d' %(UDP_PORT)).serve_forever()
class PixelVloed(object): class Canvas(object):
"""PixelVloed server class""" """PixelVloed server class"""
def __init__(self, udp_ip="127.0.0.1", udp_port=5005, debug=False): def __init__(self, queue, debug=False):
"""Init the pixelVloed server""" """Init the pixelVloed server"""
self.debug = debug self.debug = debug
self.pixeloffset = 2 self.pixeloffset = 2
self.fps = 30 self.fps = 30
self.screen = None self.screen = None
self.udp_ip = UDP_IP
self.udp_port = UDP_PORT
self.canvas() self.canvas()
self.set_title() self.set_title()
self.queue = Queue.Queue() self.queue = queue
self.receivethread = threading.Thread(target=self.Socket, args=(udp_ip, udp_port), name="ReceiveThread")
self.drawthread = threading.Thread(target=self.CanvasUpdate, name="DrawThread")
self.receivethread.start()
self.drawthread.start()
@staticmethod @staticmethod
def set_title(text=None): def set_title(text=None):
@ -44,7 +46,7 @@ class PixelVloed(object):
title += ' ' + text title += ' ' + text
pygame.display.set_caption(title) pygame.display.set_caption(title)
def canvas(self, width=768, height=1366): def canvas(self, width=1366, height=768):
"""Init the pygame canvas""" """Init the pygame canvas"""
pygame.init() pygame.init()
self.screen = pygame.display.set_mode((width, height)) self.screen = pygame.display.set_mode((width, height))
@ -57,17 +59,8 @@ class PixelVloed(object):
"""Print a pixel to the screen""" """Print a pixel to the screen"""
self.screen.set_at((x, y), (r, g, b, a)) self.screen.set_at((x, y), (r, g, b, a))
def Socket(self, ipaddress, port):
"""Sets up a udp listening socket and handles the incoming binary data"""
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.bind((ipaddress, port))
while True:
self.queue.put(sock.recvfrom(1024))
self.queue.join()
def CanvasUpdate(self): def CanvasUpdate(self):
"""Updates the screen according to self.fps"""
lasttime = time.time() lasttime = time.time()
while True: while True:
currenttime = time.time() currenttime = time.time()
@ -77,14 +70,16 @@ class PixelVloed(object):
lasttime = time.time() lasttime = time.time()
def Draw(self): def Draw(self):
data, addr = self.queue.get() """Draws pixels specified in the received packages in the queue"""
self.queue.task_done() try:
data = self.queue.get()
except:
raise
else:
preamble = struct.unpack_from("<?", data)[0] preamble = struct.unpack_from("<?", data)[0]
protocol = struct.unpack_from("<B", data, 1)[0] protocol = struct.unpack_from("<B", data, 1)[0]
pixellength = 7 #xx,yy,r,g,b pixellength = 7 #xx,yy,r,g,b
if preamble: if preamble:
if self.debug:
print 'rgba mode for %s:%d' % (addr[0], addr[1])
pixellength = 8 #xx,yy,r,g,b,a pixellength = 8 #xx,yy,r,g,b,a
pixelcount = (len(data)-1) / pixellength pixelcount = (len(data)-1) / pixellength
if self.debug: if self.debug:
@ -98,5 +93,15 @@ class PixelVloed(object):
print pixel print pixel
self.Pixel(*pixel) self.Pixel(*pixel)
class PixelVloed(DatagramServer):
"""PixelVloed server class"""
queue = Queue()
pixelcanvas = Canvas(queue)
__request_processing_greenlet = spawn(pixelcanvas.CanvasUpdate)
def handle(self, data, address):
"""Is called by the DataGramServer whenever a package is received"""
self.queue.put(data)
if __name__ == '__main__': if __name__ == '__main__':
main() main()