Boosted speed of desktop multiplexor.

Ylian Saint-Hilaire committed May 1, 2020 at 22:08 UTC 67f62cd00f5f1cc780c714f0509493fe7f08ad35
1 file changed +53 -28
meshdesktopmultiplex.js
+53 -28
@@ -63,7 +63,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
63 obj.parent = parent;
64 obj.agent = null; // Reference to the connection object that is the agent.
65 obj.viewers = []; // Array of references to all viewers.
66 - obj.viewersSendingCount = 0; // Number of viewers currently activaly sending something.
66 + obj.viewersOverflowCount = 0; // Number of viewers currently in overflow state.
67 obj.width = 0; // Current width of the display in pixels.
68 obj.height = 0; // Current height of the display in pixels.
69 obj.swidth = 0; // Current width of the display in tiles.
@@ -104,6 +104,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
104 peer.lastImageNumberSent = null;
105 peer.dataPtr = obj.firstData;
106 peer.sending = false;
107 + peer.overflow = false;
108 peer.sendQueue = [];
109 peer.paused = false;
110
@@ -133,6 +134,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
134 // Setup the agent
135 obj.agent = peer;
136 peer.sending = false;
137 + peer.overflow = false;
138 peer.sendQueue = [];
139 peer.paused = false;
140
@@ -172,6 +174,13 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
174 if (i == -1) return false;
175 obj.viewers.splice(i, 1);
176
177 + // Resume flow control if this was the peer that was limiting traffic (because it was the fastest one).
178 + if (peer.overflow == true) {
179 + obj.viewersOverflowCount--;
180 + peer.overflow = false;
181 + if ((obj.viewersOverflowCount < obj.viewers.length) && (obj.recordingFileWriting == false) && obj.agent && (obj.agent.paused == true)) { obj.agent.paused = false; obj.agent.ws._socket.resume(); }
182 + }
183 +
184 // Aggressive clean up of the viewer
185 delete peer.desktopPaused;
186 delete peer.imageCompression;
@@ -180,15 +189,9 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
189 delete peer.lastImageNumberSent;
190 delete peer.dataPtr;
191 delete peer.sending;
192 + delete peer.overflow;
193 delete peer.sendQueue;
194
185 - // Resume flow control if this was the peer that was limiting traffic (because it was the fastest one).
186 - if (peer.sending == true) {
187 - obj.viewersSendingCount--;
188 - peer.sending = false;
189 - if ((obj.viewersSendingCount < obj.viewers.length) && (obj.recordingFileWriting == false) && obj.agent && (obj.agent.paused == true)) { obj.agent.paused = false; obj.agent.ws._socket.resume(); }
190 - }
191 -
195 // Log leaving the multiplex session
196 if (obj.startTime != null) {
197 var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, userid: peer.user._id, username: peer.user.name, msg: "Left the desktop multiplex session", protocol: 2 };
@@ -237,14 +240,17 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
240 //console.log('SendToAgent', data.length);
241 if (obj.agent.sending) {
242 obj.agent.sendQueue.push(data);
240 - } else {
241 - obj.agent.ws.send(data, sendAgentNext);
243
243 - // Flow control, pause all viewers
244 - for (var i in obj.viewers) {
245 - var v = obj.viewers[i];
246 - if (v.paused == false) { v.paused = true; v.ws._socket.pause(); }
244 + // Flow control, pause all viewers is the queue is backing up
245 + if (obj.agent.sendQueue > 10) {
246 + obj.agent.overflow = true;
247 + for (var i in obj.viewers) {
248 + var v = obj.viewers[i];
249 + if (v.paused == false) { v.paused = true; v.ws._socket.pause(); }
250 + }
251 }
252 + } else {
253 + obj.agent.ws.send(data, sendAgentNext);
254 }
255 }
256
@@ -259,9 +265,12 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
265 obj.agent.sending = false;
266
267 // Flow control, resume all viewers
262 - for (var i in obj.viewers) {
263 - var v = obj.viewers[i];
264 - if (v.paused == true) { v.paused = false; v.ws._socket.resume(); }
268 + if (obj.agent.overflow == true) {
269 + obj.agent.overflow = false;
270 + for (var i in obj.viewers) {
271 + var v = obj.viewers[i];
272 + if (v.paused == true) { v.paused = false; v.ws._socket.resume(); }
273 + }
274 }
275 }
276 }
@@ -286,8 +295,27 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
295 }
296
297 // Flow control, pause the agent if needed
289 - obj.viewersSendingCount++;
290 - if ((obj.viewersSendingCount >= obj.viewers.length) && obj.agent && (obj.agent.paused == false)) { obj.agent.paused = true; obj.agent.ws._socket.pause(); }
298 + checkViewerOverflow(viewer);
299 + }
300 + }
301 +
302 + // Check if a viewer is in overflow situation
303 + function checkViewerOverflow(viewer) {
304 + if (viewer.overflow == true) return;
305 + if ((viewer.sendQueue.length > 5) || ((viewer.dataPtr != null) && (viewer.dataPtr != obj.lastData))) {
306 + viewer.overflow = true;
307 + obj.viewersOverflowCount++;
308 + if ((obj.viewersOverflowCount >= obj.viewers.length) && obj.agent && (obj.agent.paused == false)) { obj.agent.paused = true; obj.agent.ws._socket.pause(); }
309 + }
310 + }
311 +
312 + // Check if a viewer is in underflow situation
313 + function checkViewerUnderflow(viewer) {
314 + if (viewer.overflow == false) return;
315 + if ((viewer.sendQueue.length <= 5) && ((viewer.dataPtr == null) || (viewer.dataPtr == obj.lastData))) {
316 + viewer.overflow = false;
317 + obj.viewersOverflowCount--;
318 + if ((obj.viewersOverflowCount < obj.viewers.length) && (obj.recordingFileWriting == false) && obj.agent && (obj.agent.paused == true)) { obj.agent.paused = false; obj.agent.ws._socket.resume(); }
319 }
320 }
321
@@ -296,12 +324,13 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
324 if (viewer.sendQueue == null) return;
325 if (viewer.sendQueue.length > 0) {
326 // Send from the pending send queue
299 - if (viewer.sending == false) { viewer.sending = true; obj.viewersSendingCount++; }
327 + if (viewer.sending == false) { viewer.sending = true; }
328 if (viewer.slowRelay) {
329 setTimeout(function () { try { viewer.ws.send(viewer.sendQueue.shift(), function () { sendViewerNext(viewer); }); } catch (ex) { } }, viewer.slowRelay);
330 } else {
331 try { viewer.ws.send(viewer.sendQueue.shift(), function () { sendViewerNext(viewer); }); } catch (ex) { }
332 }
333 + checkViewerOverflow(viewer);
334 } else {
335 if (viewer.dataPtr != null) {
336 // Send the next image
@@ -317,18 +346,14 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
346 }
347
348 // Flow control, pause the agent if needed
320 - if (viewer.sending == false) {
321 - viewer.sending = true;
322 - obj.viewersSendingCount++;
323 - if (((obj.viewersSendingCount >= obj.viewers.length) || (obj.recordingFileWriting == true)) && obj.agent && (obj.agent.paused == false)) { obj.agent.paused = true; obj.agent.ws._socket.pause(); }
324 - }
349 + if (viewer.sending == false) { viewer.sending = true; }
350 + checkViewerOverflow(viewer);
351 } else {
352 // Nothing to send
353 viewer.sending = false;
354
355 // Flow control, resume agent if needed
330 - obj.viewersSendingCount--;
331 - if ((obj.viewersSendingCount < obj.viewers.length) && (obj.recordingFileWriting == false) && obj.agent && (obj.agent.paused == true)) { obj.agent.paused = false; obj.agent.ws._socket.resume(); }
356 + checkViewerUnderflow(viewer);
357 }
358 }
359 }
@@ -339,7 +364,7 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
364 obj.recordingFileWriting = true;
365 recordData(true, data, function () {
366 obj.recordingFileWriting = false;
342 - if ((obj.viewersSendingCount < obj.viewers.length) && obj.agent && (obj.agent.paused == true)) { obj.agent.paused = false; obj.agent.ws._socket.resume(); }
367 + if ((obj.viewersOverflowCount < obj.viewers.length) && obj.agent && (obj.agent.paused == true)) { obj.agent.paused = false; obj.agent.ws._socket.resume(); }
368 obj.processAgentData(data);
369 });
370 } else {