From 7c13ea2f2b9aa11859c44f01dfeef29d402b276c Mon Sep 17 00:00:00 2001 From: Sophie Alpert Date: Wed, 10 Apr 2019 16:31:11 -0700 Subject: [PATCH] Improve bridge batching logic Fixes #132. --- src/bridge.js | 50 +++++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/bridge.js b/src/bridge.js index 454c4b9cde..9b3c3dd318 100644 --- a/src/bridge.js +++ b/src/bridge.js @@ -13,7 +13,6 @@ type Message = {| export default class Bridge extends EventEmitter { _messageQueue: Array = []; - _time: number | null = null; _timeoutID: TimeoutID | null = null; _wall: Wall; @@ -28,34 +27,39 @@ export default class Bridge extends EventEmitter { } send(event: string, payload: any, transferable?: Array) { - const time = this._time; + // When we receive a message: + // - we add it to our queue of messages to be sent + // - if there hasn't been a message recently, we set a timer for 0 ms in + // the future, allowing all messages created in the same tick to be sent + // together + // - if there *has* been a message flushed in the last BATCH_DURATION ms + // (or we're waiting for our setTimeout-0 to fire), then _timeoutID will + // be set, and we'll simply add to the queue and wait for that - if (time === null) { - this._wall.send(event, payload, transferable); - this._time = Date.now(); - } else { - this._messageQueue.push(event, payload, transferable); - - const now = Date.now(); - if (now - time > BATCH_DURATION) { - this._flush(); - } else { - this._timeoutID = setTimeout(this._flush, BATCH_DURATION); - } + this._messageQueue.push(event, payload, transferable); + if (!this._timeoutID) { + this._timeoutID = setTimeout(this._flush, 0); } } _flush = () => { - while (this._messageQueue.length) { - this._wall.send.apply(this._wall, this._messageQueue.splice(0, 3)); - } + clearTimeout(this._timeoutID); + this._timeoutID = null; - if (this._timeoutID !== null) { - clearTimeout(this._timeoutID); - this._timeoutID = null; - } + if (this._messageQueue.length) { + for (let i = 0; i < this._messageQueue.length; i += 3) { + this._wall.send( + this._messageQueue[i], + this._messageQueue[i + 1], + this._messageQueue[i + 2], + ); + } + this._messageQueue.length = 0; - this._messageQueue = []; - this._time = null; + // Check again for queued messages in BATCH_DURATION ms. This will keep + // flushing in a loop as long as messages continue to be added. Once no + // more are, the timer expires. + this._timeoutID = setTimeout(this._flush, BATCH_DURATION); + } }; }