Changeset - 7d5d6e7bc526
[Not reviewed]
default
0 3 0
Drew Perttula - 8 years ago 2017-06-03 19:58:42
drewp@bigasterisk.com
collector web view speedups- don't json encode all devs all the time
Ignore-this: ed01dc070b5e21303b0a62ff5d814b30
3 files changed with 35 insertions and 18 deletions:
0 comments (0 inline, 0 general)
bin/collector
Show inline comments
 
@@ -57,37 +57,51 @@ def startZmq(port, collector):
 
            collector.setAttrs(client, clientSession, settings, sendTime)
 
    s.onPull = onPull
 

	
 
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):
 
        self.clients = [[c, t] for c, t in self.clients if c != client]
 
        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 = []
 
        for attr, val in attrs.items():
 
            output, index = outputMap[(dev, attr)]
 
            attrRows.append({'attr': attr.rsplit('/')[-1],
 
@@ -169,12 +183,14 @@ def main():
 
                      help="logging.DEBUG")
 
    parser.add_option("--loadtest", action="store_true",
 
                      help="call myself with some synthetic load then exit")
 
    (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)
 
    reactor.run()
 

	
 
if __name__ == '__main__':
light9/collector/collector.py
Show inline comments
 
@@ -166,13 +166,13 @@ class Collector(Generic[ClientType, Clie
 
            for outputAttr, value in attrs.iteritems():
 
                self.setAttr(device, outputAttr, value, pendingOut)
 

	
 
        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)
 
            ))
 

	
 
    def setAttr(self, device, outputAttr, value, pendingOut):
 
        output, index = self.outputMap[(device, outputAttr)]
light9/effect/sequencer.py
Show inline comments
 
@@ -148,14 +148,15 @@ class CodeWatcher(object):
 
        # in case we got an event at the start of the write
 
        reactor.callLater(.1, go) 
 
    
 
        
 

	
 
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)
 

	
 
        self.recentUpdateTimes = []
 
        self.lastStatLog = 0
 
        self._compileGraphCall = None
 
@@ -185,13 +186,13 @@ class Sequencer(object):
 
        self.recentUpdateTimes = self.recentUpdateTimes[-20:] + [now]
 
        stats.recentFps = len(self.recentUpdateTimes) / (self.recentUpdateTimes[-1] - self.recentUpdateTimes[0] + .0001)
 
        if now > self.lastStatLog + 10:
 
            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
 
        if 't' not in musicState:
 
            return
 
        t = musicState['t']
0 comments (0 inline, 0 general)