changeset 1596:7d5d6e7bc526

collector web view speedups- don't json encode all devs all the time Ignore-this: ed01dc070b5e21303b0a62ff5d814b30
author Drew Perttula <drewp@bigasterisk.com>
date Sat, 03 Jun 2017 19:58:42 +0000
parents 013cbd7a0f08
children 616b22296156
files bin/collector light9/collector/collector.py light9/effect/sequencer.py
diffstat 3 files changed, 35 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/bin/collector	Sat Jun 03 09:20:04 2017 +0000
+++ b/bin/collector	Sat Jun 03 19:58:42 2017 +0000
@@ -60,9 +60,11 @@
 class WebListeners(object):
     def __init__(self):
         self.clients = []
-
+        self.pendingMessageForDev = {} # dev: (attrs, outputmap)
+        self.lastFlush = 0
+        
     def addClient(self, client):
-        self.clients.append([client, {}])
+        self.clients.append([client, {}]) # seen = {dev: attrs}
         log.info('added client %s', client)
 
     def delClient(self, client):
@@ -70,21 +72,33 @@
         log.info('delClient %s, %s left', client, len(self.clients))
         
     def outputAttrsSet(self, dev, attrs, outputMap):
-        now = time.time()
+        """called often- don't be slow"""
+
+        self.pendingMessageForDev[dev] = (attrs, outputMap)
+        self._flush()
 
-        msg = self.makeMsg(dev, attrs, outputMap)
+    def _flush(self):
+        now = time.time()
+        if now < self.lastFlush + .05 or not self.clients:
+            return
+        self.lastFlush = now
+
+        while self.pendingMessageForDev:
+            dev, (attrs, outputMap) = self.pendingMessageForDev.popitem()
 
-        # this omits repeats, but can still send many
-        # messages/sec. Not sure if piling up messages for the browser
-        # could lead to slowdowns in the real dmx output.
-        for client, seen in self.clients:
-            for m, t in seen.items():
-                if t < now - 5:
-                    del seen[m]
-            if msg in seen:
-                continue
-            seen[msg] = now
-            client.sendMessage(msg)
+            msg = None # lazy, since makeMsg is slow
+            
+            # this omits repeats, but can still send many
+            # messages/sec. Not sure if piling up messages for the browser
+            # could lead to slowdowns in the real dmx output.
+            for client, seen in self.clients:
+                if seen.get(dev) == attrs:
+                    continue
+                if msg is None:
+                    msg = self.makeMsg(dev, attrs, outputMap)
+
+                seen[dev] = attrs
+                client.sendMessage(msg)
 
     def makeMsg(self, dev, attrs, outputMap):
         attrRows = []
@@ -172,6 +186,8 @@
     (options, args) = parser.parse_args()
     log.setLevel(logging.DEBUG if options.verbose else logging.INFO)
 
+    logging.getLogger('colormath').setLevel(logging.INFO)
+    
     graph = SyncedGraph(networking.rdfdb.url, "collector")
 
     graph.initiallySynced.addCallback(lambda _: launch(graph, options.loadtest)).addErrback(log.error)
--- a/light9/collector/collector.py	Sat Jun 03 09:20:04 2017 +0000
+++ b/light9/collector/collector.py	Sat Jun 03 19:58:42 2017 +0000
@@ -169,7 +169,7 @@
         dt1 = 1000 * (time.time() - now)
         self.flush(pendingOut)
         dt2 = 1000 * (time.time() - now)
-        if dt1 > 10:
+        if dt1 > 15:
             log.warn("slow setAttrs: %.1fms -> flush -> %.1fms. lr %s da %s oa %s" % (
                 dt1, dt2, len(self.lastRequest), len(deviceAttrs), len(outputAttrs)
             ))
--- a/light9/effect/sequencer.py	Sat Jun 03 09:20:04 2017 +0000
+++ b/light9/effect/sequencer.py	Sat Jun 03 19:58:42 2017 +0000
@@ -151,8 +151,9 @@
         
 
 class Sequencer(object):
-    def __init__(self, graph, sendToCollector):
+    def __init__(self, graph, sendToCollector, fps=30):
         self.graph = graph
+        self.fps = 30
         self.sendToCollector = sendToCollector
         self.music = MusicTime(period=.2, pollCurvecalc=False)
 
@@ -188,7 +189,7 @@
             log.info("%.2f fps", stats.recentFps)
             self.lastStatLog = now
         
-        reactor.callLater(1/50, self.update)
+        reactor.callLater(1 / self.fps, self.update)
 
         musicState = self.music.getLatest()
         song = URIRef(musicState['song']) if musicState.get('song') else None