perf(graph): add adaptive layout degrade and defer persist clone

This commit is contained in:
Youzini-afk
2026-04-13 12:46:05 +08:00
parent 14d1b98d5b
commit 29f21857e7
2 changed files with 57 additions and 2 deletions

View File

@@ -9812,7 +9812,6 @@ function queueGraphPersistToIndexedDb(
) { ) {
const normalizedChatId = normalizeChatIdCandidate(chatId); const normalizedChatId = normalizeChatIdCandidate(chatId);
if (!normalizedChatId || !graph) return; if (!normalizedChatId || !graph) return;
const graphSnapshot = cloneGraphForPersistence(graph, normalizedChatId);
const normalizedRevision = normalizeIndexedDbRevision(revision); const normalizedRevision = normalizeIndexedDbRevision(revision);
const latestQueuedRevision = normalizeIndexedDbRevision( const latestQueuedRevision = normalizeIndexedDbRevision(
@@ -9843,6 +9842,7 @@ function queueGraphPersistToIndexedDb(
revision: normalizedRevision, revision: normalizedRevision,
}; };
} }
const graphSnapshot = cloneGraphForPersistence(graph, normalizedChatId);
return await saveGraphToIndexedDb(normalizedChatId, graphSnapshot, { return await saveGraphToIndexedDb(normalizedChatId, graphSnapshot, {
revision: normalizedRevision, revision: normalizedRevision,
reason, reason,

View File

@@ -44,6 +44,17 @@ const DEFAULT_LAYOUT_CONFIG = {
neuralMinGap: 12, neuralMinGap: 12,
}; };
const ADAPTIVE_NEURAL_LAYOUT_POLICY = Object.freeze({
reduceIterationsNodes: 220,
reduceIterationsEdges: 1200,
reduceIterationsCap: 56,
strongReduceNodes: 360,
strongReduceEdges: 2200,
strongReduceCap: 24,
skipSimulationNodes: 520,
skipSimulationEdges: 3600,
});
const MIN_USABLE_CANVAS_DIMENSION = 48; const MIN_USABLE_CANVAS_DIMENSION = 48;
/** 兼容旧版 forceConfig召回卡片等 */ /** 兼容旧版 forceConfig召回卡片等 */
@@ -296,7 +307,10 @@ export class GraphRenderer {
const parts = partitionNodesByScope(this.nodes, this._userPovAliasSet); const parts = partitionNodesByScope(this.nodes, this._userPovAliasSet);
this._regionPanels = this._computeRegionPanels(W, H, parts); this._regionPanels = this._computeRegionPanels(W, H, parts);
this._layoutAllPartitions(parts); this._layoutAllPartitions(parts);
this._simulateNeuralWithinRegions(this.config.neuralIterations); const neuralPlan = this._resolveNeuralSimulationPlan();
if (!neuralPlan.skip && neuralPlan.iterations > 0) {
this._simulateNeuralWithinRegions(neuralPlan.iterations);
}
if (prevSelectedId) { if (prevSelectedId) {
this.selectedNode = this.nodeMap.get(prevSelectedId) || null; this.selectedNode = this.nodeMap.get(prevSelectedId) || null;
@@ -575,6 +589,47 @@ export class GraphRenderer {
return ideal; return ideal;
} }
_resolveNeuralSimulationPlan() {
const nodeCount = Array.isArray(this.nodes) ? this.nodes.length : 0;
const edgeCount = Array.isArray(this.edges) ? this.edges.length : 0;
const baseIterations = Math.max(
8,
Math.min(220, Number(this.config.neuralIterations) || 80),
);
let iterations = baseIterations;
let skip = false;
if (
nodeCount >= ADAPTIVE_NEURAL_LAYOUT_POLICY.skipSimulationNodes ||
edgeCount >= ADAPTIVE_NEURAL_LAYOUT_POLICY.skipSimulationEdges
) {
skip = true;
iterations = 0;
} else if (
nodeCount >= ADAPTIVE_NEURAL_LAYOUT_POLICY.strongReduceNodes ||
edgeCount >= ADAPTIVE_NEURAL_LAYOUT_POLICY.strongReduceEdges
) {
iterations = Math.min(
iterations,
ADAPTIVE_NEURAL_LAYOUT_POLICY.strongReduceCap,
);
} else if (
nodeCount >= ADAPTIVE_NEURAL_LAYOUT_POLICY.reduceIterationsNodes ||
edgeCount >= ADAPTIVE_NEURAL_LAYOUT_POLICY.reduceIterationsEdges
) {
iterations = Math.min(
iterations,
ADAPTIVE_NEURAL_LAYOUT_POLICY.reduceIterationsCap,
);
}
return {
skip,
iterations,
};
}
/** /**
* 分区内一次性力导向:斥力 + 同区边弹簧 + 弱向心,稳定后停止(无帧循环) * 分区内一次性力导向:斥力 + 同区边弹簧 + 弱向心,稳定后停止(无帧循环)
*/ */