From 574ebecd2dec986ec5a92126b8c8f12cbacd1498 Mon Sep 17 00:00:00 2001 From: "Benjamin Arntzen (aider)" Date: Wed, 3 Jul 2024 23:23:06 -0300 Subject: [PATCH] Implemented WebSocket compression and batched updates to improve performance. --- public/app.js | 79 +++++++++++++++++++++++++++------------------------ server.js | 40 +++++++++++++++----------- 2 files changed, 66 insertions(+), 53 deletions(-) diff --git a/public/app.js b/public/app.js index b1c5ff7..adaef8f 100644 --- a/public/app.js +++ b/public/app.js @@ -1,5 +1,7 @@ const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; -const socket = new WebSocket(`${protocol}//${window.location.host}`); +const socket = new WebSocket(`${protocol}//${window.location.host}`, { + perMessageDeflate: true +}); socket.addEventListener('open', () => { console.log('WebSocket connection established'); @@ -374,51 +376,54 @@ function updateNodes() { updateNodes(); socket.addEventListener('message', (event) => { - const logData = JSON.parse(event.data); - const { msg_hash, receivedTime, peerId, newNode } = logData; + const batchedUpdates = JSON.parse(event.data); + + batchedUpdates.forEach(logData => { + const { msg_hash, receivedTime, peerId, newNode } = logData; - if (newNode) { - nodes.add({ - id: peerId, - title: `Node ${peerId}`, - borderWidth: 0, - borderWidthSelected: 2, - color: { - background: DEFAULT_COLOR, - border: DEFAULT_COLOR, - highlight: { + if (newNode) { + nodes.add({ + id: peerId, + title: `Node ${peerId}`, + borderWidth: 0, + borderWidthSelected: 2, + color: { background: DEFAULT_COLOR, - border: DEFAULT_COLOR + border: DEFAULT_COLOR, + highlight: { + background: DEFAULT_COLOR, + border: DEFAULT_COLOR + } + } + }); + } + + const colorHex = generateColorFromHash(msg_hash); + + nodes.update({ + id: peerId, + color: { + background: colorHex, + highlight: { + background: colorHex } } }); - } - const colorHex = generateColorFromHash(msg_hash); - - nodes.update({ - id: peerId, - color: { - background: colorHex, - highlight: { - background: colorHex - } + // Add or update edge + const edgeId = `${msg_hash}-${peerId}`; + if (!edges.get(edgeId)) { + edges.add({ + id: edgeId, + from: msg_hash, + to: peerId, + arrows: 'to', + color: { color: '#ffffff', opacity: 0.5 } + }); } }); - // Add or update edge - const edgeId = `${msg_hash}-${peerId}`; - if (!edges.get(edgeId)) { - edges.add({ - id: edgeId, - from: msg_hash, - to: peerId, - arrows: 'to', - color: { color: '#ffffff', opacity: 0.5 } - }); - } - - // Update counter immediately + // Update counter after processing all updates updateCounter(); }); diff --git a/server.js b/server.js index a48f4a8..5abd03e 100644 --- a/server.js +++ b/server.js @@ -3,11 +3,15 @@ const http = require('http'); const WebSocket = require('ws'); const axios = require('axios'); const path = require('path'); +const zlib = require('zlib'); const argv = require('yargs').argv; const app = express(); const server = http.createServer(app); -const wss = new WebSocket.Server({ server }); +const wss = new WebSocket.Server({ + server, + perMessageDeflate: true +}); let logCache = new Set(); let pollingInterval = 50; // Start with 50ms interval @@ -165,6 +169,9 @@ function parseLogLines(data) { return validLogs; } +let updateBatch = []; +const BATCH_INTERVAL = 1000 / 60; // ~16.67ms for 60 updates per second + function processLogs(logs) { logs.forEach((log, index) => { debugLog(`Processing log at index ${index}`); @@ -193,21 +200,8 @@ function processLogs(logs) { }; logCache.add(`node-${peerId}`); - - const eventData = { - msg_hash: logData.msg_hash, - receivedTime: logData.receivedTime, - peerId: logData.peerId, - newNode: logData.newNode - }; - - wss.clients.forEach(client => { - if (client.readyState === WebSocket.OPEN) { - debugLog(`Sending event to client ${client._socket.remoteAddress}:`, eventData); - client.send(JSON.stringify(eventData)); - eventsSentToClients++; - } - }); + updateBatch.push(logData); + eventsSentToClients++; } else { debugLog(`Duplicate log found: ${logIdentifier}`); } @@ -221,3 +215,17 @@ function processLogs(logs) { } }); } + +function sendBatchedUpdates() { + if (updateBatch.length > 0) { + const batchData = JSON.stringify(updateBatch); + wss.clients.forEach(client => { + if (client.readyState === WebSocket.OPEN) { + client.send(batchData); + } + }); + updateBatch = []; + } +} + +setInterval(sendBatchedUpdates, BATCH_INTERVAL);