mirror of
https://github.com/wisplite/BLE-mesh-sim.git
synced 2026-10-30 13:32:21 -05:00
sendPacket rendering optimizations
This commit is contained in:
@@ -33,6 +33,7 @@ class CompleteNodeOnEdgeEngine {
|
|||||||
this.speedMultiplier = 1;
|
this.speedMultiplier = 1;
|
||||||
this.timeAccumulator = 0;
|
this.timeAccumulator = 0;
|
||||||
this._movementInitialized = false;
|
this._movementInitialized = false;
|
||||||
|
this._isDragging = false;
|
||||||
|
|
||||||
// Keep linksByEdges up-to-date for dynamic graph changes
|
// Keep linksByEdges up-to-date for dynamic graph changes
|
||||||
if (this.nodes && this.nodes.on) {
|
if (this.nodes && this.nodes.on) {
|
||||||
@@ -127,6 +128,7 @@ class CompleteNodeOnEdgeEngine {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.network.on('dragging', (params) => {
|
this.network.on('dragging', (params) => {
|
||||||
|
this._isDragging = true;
|
||||||
if (params.edges.length <= 0) {
|
if (params.edges.length <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -139,6 +141,10 @@ class CompleteNodeOnEdgeEngine {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.network.on('dragEnd', (params) => {
|
||||||
|
this._isDragging = false;
|
||||||
|
});
|
||||||
|
|
||||||
this.network.on('physicsMoving', (params) => {
|
this.network.on('physicsMoving', (params) => {
|
||||||
this.edgesMoved = true;
|
this.edgesMoved = true;
|
||||||
// Only clear cache for edges that have moving dots
|
// Only clear cache for edges that have moving dots
|
||||||
@@ -284,7 +290,8 @@ class CompleteNodeOnEdgeEngine {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Request canvas redraw without forcing full network re-render
|
// Request canvas redraw without forcing full network re-render
|
||||||
if (this.movingDots.size > 0) {
|
// Skip during dragging as vis-network handles redraws automatically
|
||||||
|
if (this.movingDots.size > 0 && !this._isDragging) {
|
||||||
this.network.canvas.body.emitter.emit("_requestRedraw");
|
this.network.canvas.body.emitter.emit("_requestRedraw");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,55 @@ var markNeighborRafs = new Set();
|
|||||||
var nodeUpdateCache = [];
|
var nodeUpdateCache = [];
|
||||||
var edgeUpdateCache = [];
|
var edgeUpdateCache = [];
|
||||||
|
|
||||||
|
// Debounced batched updater for nodes/edges to reduce render thrash
|
||||||
|
var debouncedVis = (function () {
|
||||||
|
var nodeMap = new Map();
|
||||||
|
var edgeMap = new Map();
|
||||||
|
var timer = null;
|
||||||
|
var debounceMs = 50; // flush after 50ms of inactivity
|
||||||
|
|
||||||
|
function flush() {
|
||||||
|
timer = null;
|
||||||
|
if (nodeMap.size) {
|
||||||
|
nodes.update(Array.from(nodeMap.values()));
|
||||||
|
nodeMap.clear();
|
||||||
|
}
|
||||||
|
if (edgeMap.size) {
|
||||||
|
edges.update(Array.from(edgeMap.values()));
|
||||||
|
edgeMap.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function schedule() {
|
||||||
|
if (timer) clearTimeout(timer);
|
||||||
|
timer = setTimeout(flush, debounceMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
function enqueueNode(update) {
|
||||||
|
// keep only the latest update per id
|
||||||
|
var existing = nodeMap.get(update.id) || {};
|
||||||
|
nodeMap.set(update.id, Object.assign({}, existing, update));
|
||||||
|
schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
function enqueueEdge(update) {
|
||||||
|
var existing = edgeMap.get(update.id) || {};
|
||||||
|
edgeMap.set(update.id, Object.assign({}, existing, update));
|
||||||
|
schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
function enqueueEdges(updates) {
|
||||||
|
for (var i = 0; i < updates.length; i++) {
|
||||||
|
var u = updates[i];
|
||||||
|
var existing = edgeMap.get(u.id) || {};
|
||||||
|
edgeMap.set(u.id, Object.assign({}, existing, u));
|
||||||
|
}
|
||||||
|
schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
return { enqueueNode: enqueueNode, enqueueEdge: enqueueEdge, enqueueEdges: enqueueEdges, flush: flush };
|
||||||
|
})();
|
||||||
|
|
||||||
function smoothColorTransition(color1, color2, min, max, current) {
|
function smoothColorTransition(color1, color2, min, max, current) {
|
||||||
// Clamp current between min and max
|
// Clamp current between min and max
|
||||||
const clamped = Math.min(Math.max(current, min), max);
|
const clamped = Math.min(Math.max(current, min), max);
|
||||||
@@ -123,15 +172,10 @@ onEdgeEngine.setArrivalCallback(async ({ from, to, dot }) => {
|
|||||||
// Batch edge updates for better performance
|
// Batch edge updates for better performance
|
||||||
if (document.getElementById('showTTL').checked) {
|
if (document.getElementById('showTTL').checked) {
|
||||||
const edgeColor = smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1);
|
const edgeColor = smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1);
|
||||||
edges.update([
|
debouncedVis.enqueueEdges([
|
||||||
{id: `${from}->${to}`, color: {color: edgeColor, highlight: edgeColor}},
|
{id: `${from}->${to}`, color: {color: edgeColor, highlight: edgeColor}},
|
||||||
{id: `${to}->${from}`, color: {color: edgeColor, highlight: edgeColor}}
|
{id: `${to}->${from}`, color: {color: edgeColor, highlight: edgeColor}}
|
||||||
]);
|
]);
|
||||||
} else {
|
|
||||||
edges.update([
|
|
||||||
{id: `${from}->${to}`, color: {color: '#2b7ce9', highlight: '#2b7ce9'}},
|
|
||||||
{id: `${to}->${from}`, color: {color: '#2b7ce9', highlight: '#2b7ce9'}}
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
if (nodeTable[to].packetCache.has(dot.id.split('-')[0])) {
|
if (nodeTable[to].packetCache.has(dot.id.split('-')[0])) {
|
||||||
return;
|
return;
|
||||||
@@ -142,9 +186,7 @@ onEdgeEngine.setArrivalCallback(async ({ from, to, dot }) => {
|
|||||||
var originNode = dot.id.split('-')[3];
|
var originNode = dot.id.split('-')[3];
|
||||||
ttl--;
|
ttl--;
|
||||||
if (document.getElementById('showTTL').checked) {
|
if (document.getElementById('showTTL').checked) {
|
||||||
nodes.update({id: to, color: {background: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl)}});
|
debouncedVis.enqueueNode({id: to, color: {background: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl)}});
|
||||||
} else {
|
|
||||||
nodes.update({id: to, color: {background: '#97c2fc'}});
|
|
||||||
}
|
}
|
||||||
if (ttl > 0) {
|
if (ttl > 0) {
|
||||||
const neighborsSnapshot = nodeTable[to].connections.slice();
|
const neighborsSnapshot = nodeTable[to].connections.slice();
|
||||||
@@ -167,7 +209,15 @@ onEdgeEngine.setArrivalCallback(async ({ from, to, dot }) => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (document.getElementById('showTTL').checked) {
|
if (document.getElementById('showTTL').checked) {
|
||||||
markNeighborsAsFailed(to, from, packetId);
|
// Use a unique marker packet ID to bypass cache and mark unreachable nodes
|
||||||
|
const markerPacketId = `${packetId}`;
|
||||||
|
const neighborsSnapshot = nodeTable[to].connections.slice();
|
||||||
|
for (let neighbor of neighborsSnapshot) {
|
||||||
|
if (neighbor === from || neighbor === originNode) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
quickPacketRaf(neighbor, `${markerPacketId}-${generateRealisticLabel()}-${0}-${originNode}`, from);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -283,9 +333,9 @@ function quickRoute(startNode, packetInfo, fromNode) {
|
|||||||
|
|
||||||
// Batch updates for better performance
|
// Batch updates for better performance
|
||||||
if (document.getElementById('showTTL').checked) {
|
if (document.getElementById('showTTL').checked) {
|
||||||
nodes.update({id: nodeId, color: {background: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl)}});
|
debouncedVis.enqueueNode({id: nodeId, color: {background: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl)}});
|
||||||
const edgeColor = smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1);
|
const edgeColor = smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1);
|
||||||
edges.update([
|
debouncedVis.enqueueEdges([
|
||||||
{id: `${from}->${nodeId}`, color: {color: edgeColor, highlight: edgeColor}},
|
{id: `${from}->${nodeId}`, color: {color: edgeColor, highlight: edgeColor}},
|
||||||
{id: `${nodeId}->${from}`, color: {color: edgeColor, highlight: edgeColor}}
|
{id: `${nodeId}->${from}`, color: {color: edgeColor, highlight: edgeColor}}
|
||||||
]);
|
]);
|
||||||
@@ -338,7 +388,7 @@ async function routePacket(currentNode, goalNode, packetInfo, first=false) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (document.getElementById('showTTL').checked) {
|
if (document.getElementById('showTTL').checked) {
|
||||||
nodes.update({id: currentNode, color: {background: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl)}});
|
debouncedVis.enqueueNode({id: currentNode, color: {background: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl)}});
|
||||||
} else {
|
} else {
|
||||||
if (first) {
|
if (first) {
|
||||||
nodes.update({id: currentNode, color: {background: '#ff00d9'}});
|
nodes.update({id: currentNode, color: {background: '#ff00d9'}});
|
||||||
@@ -369,7 +419,7 @@ async function routePacket(currentNode, goalNode, packetInfo, first=false) {
|
|||||||
// Batch edge updates for better performance
|
// Batch edge updates for better performance
|
||||||
if (document.getElementById('showTTL').checked) {
|
if (document.getElementById('showTTL').checked) {
|
||||||
const edgeColor = smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1);
|
const edgeColor = smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1);
|
||||||
edges.update([
|
debouncedVis.enqueueEdges([
|
||||||
{id: `${currentNode}->${nextNode}`, color: {color: edgeColor, highlight: edgeColor}},
|
{id: `${currentNode}->${nextNode}`, color: {color: edgeColor, highlight: edgeColor}},
|
||||||
{id: `${nextNode}->${currentNode}`, color: {color: edgeColor, highlight: edgeColor}}
|
{id: `${nextNode}->${currentNode}`, color: {color: edgeColor, highlight: edgeColor}}
|
||||||
]);
|
]);
|
||||||
@@ -465,9 +515,9 @@ const markNeighborsAsFailed = (startNodeId, from, packetId, visited = new Set(),
|
|||||||
tasks.push({ nodeId: neighbor, from: task.nodeId, neighbors: nextNeighbors, idx: 0 });
|
tasks.push({ nodeId: neighbor, from: task.nodeId, neighbors: nextNeighbors, idx: 0 });
|
||||||
|
|
||||||
// batch visuals
|
// batch visuals
|
||||||
nodeBatch.push({ id: neighbor, color: { background: 'white' } });
|
nodeBatch.push({ id: neighbor, color: { background: '#878787' } });
|
||||||
edgeBatch.push({ id: `${task.nodeId}->${neighbor}`, color: { color: 'white', highlight: '#97c2fc' } });
|
edgeBatch.push({ id: `${task.nodeId}->${neighbor}`, color: { color: '#878787', highlight: '#878787' } });
|
||||||
edgeBatch.push({ id: `${neighbor}->${task.nodeId}`, color: { color: 'white', highlight: '#97c2fc' } });
|
edgeBatch.push({ id: `${neighbor}->${task.nodeId}`, color: { color: '#878787', highlight: '#878787' } });
|
||||||
|
|
||||||
ops++;
|
ops++;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user