From a521f4c873e9c1374efd21913418cf3c14f2ad81 Mon Sep 17 00:00:00 2001 From: modeco80 Date: Tue, 20 Aug 2024 01:05:44 -0400 Subject: [PATCH] Queue rect updates for each frame (and.. maybe? do rects in parallel) both superqemu and vncvm have supported this but I never did it for some reason. its noticably faster than before. testing seems to imply that its actually slightly faster without the batcher enabled (maybe because it's actually able to split the work now if I had to guess) --- cvmts/src/CollabVMServer.ts | 70 +++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/cvmts/src/CollabVMServer.ts b/cvmts/src/CollabVMServer.ts index 9566136..8b56199 100644 --- a/cvmts/src/CollabVMServer.ts +++ b/cvmts/src/CollabVMServer.ts @@ -93,6 +93,9 @@ export default class CollabVMServer { // Ban manager private banmgr: BanManager; + // queue of rects, reset every frame + private rectQueue: Rect[] = []; + private logger = pino({ name: 'CVMTS.Server' }); constructor(config: IConfig, vm: VM, banmgr: BanManager, auth: AuthManager | null, geoipReader: ReaderModel | null) { @@ -131,6 +134,7 @@ export default class CollabVMServer { // well aware this sucks but whatever self.VM.GetDisplay().on('resize', (size: Size) => self.OnDisplayResized(size)); self.VM.GetDisplay().on('rect', (rect: Rect) => self.OnDisplayRectangle(rect)); + self.VM.GetDisplay().on('frame', () => self.OnDisplayFrame()); } if (newState == VMState.Stopped) { @@ -144,6 +148,7 @@ export default class CollabVMServer { // this sucks too fix this self.VM.GetDisplay().on('resize', (size: Size) => self.OnDisplayResized(size)); self.VM.GetDisplay().on('rect', (rect: Rect) => self.OnDisplayRectangle(rect)); + self.VM.GetDisplay().on('frame', () => self.OnDisplayFrame()); } // authentication manager @@ -838,29 +843,8 @@ export default class CollabVMServer { } } - private async OnDisplayRectangle(rect: Rect) { - let encoded = await this.MakeRectData(rect); - let encodedb64 = encoded.toString('base64'); - let bmsg: CollabVMProtocolMessage = { - type: CollabVMProtocolMessageType.rect, - rect: { - x: rect.x, - y: rect.y, - data: encoded - } - }; - var encodedbin = msgpack.encode(bmsg); - this.clients - .filter((c) => c.connectedToNode || c.viewMode == 1) - .forEach((c) => { - if (this.screenHidden && c.rank == Rank.Unregistered) return; - if (c.Capabilities.bin) { - c.socket.sendBinary(encodedbin); - } else { - c.sendMsg(cvm.guacEncode('png', '0', '0', rect.x.toString(), rect.y.toString(), encodedb64)); - c.sendMsg(cvm.guacEncode('sync', Date.now().toString())); - } - }); + private OnDisplayRectangle(rect: Rect) { + this.rectQueue.push(rect); } private OnDisplayResized(size: Size) { @@ -872,6 +856,46 @@ export default class CollabVMServer { }); } + private async OnDisplayFrame() { + let self = this; + + let doRect = async (rect: Rect) => { + let encoded = await this.MakeRectData(rect); + let encodedb64 = encoded.toString('base64'); + let bmsg: CollabVMProtocolMessage = { + type: CollabVMProtocolMessageType.rect, + rect: { + x: rect.x, + y: rect.y, + data: encoded + } + }; + + var encodedbin = msgpack.encode(bmsg); + + self.clients + .filter((c) => c.connectedToNode || c.viewMode == 1) + .forEach((c) => { + if (self.screenHidden && c.rank == Rank.Unregistered) return; + if (c.Capabilities.bin) { + c.socket.sendBinary(encodedbin); + } else { + c.sendMsg(cvm.guacEncode('png', '0', '0', rect.x.toString(), rect.y.toString(), encodedb64)); + c.sendMsg(cvm.guacEncode('sync', Date.now().toString())); + } + }); + }; + + let promises: Promise[] = []; + + for(let rect of self.rectQueue) + promises.push(doRect(rect)); + + this.rectQueue = []; + + await Promise.all(promises); + } + private async SendFullScreenWithSize(client: User) { let display = this.VM.GetDisplay(); if (display == null) return;