diff --git a/bin/collector b/bin/collector --- a/bin/collector +++ b/bin/collector @@ -60,9 +60,11 @@ def startZmq(port, collector): 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 @@ class WebListeners(object): 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 @@ def main(): (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) diff --git a/light9/collector/collector.py b/light9/collector/collector.py --- a/light9/collector/collector.py +++ b/light9/collector/collector.py @@ -169,7 +169,7 @@ class Collector(Generic[ClientType, Clie 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) )) diff --git a/light9/effect/sequencer.py b/light9/effect/sequencer.py --- a/light9/effect/sequencer.py +++ b/light9/effect/sequencer.py @@ -151,8 +151,9 @@ class CodeWatcher(object): 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 @@ class Sequencer(object): 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