[fix] Optimize subgraph serialization to exclude unused definitions (#1185)

This commit is contained in:
Christian Byrne
2025-08-01 21:40:29 -07:00
committed by GitHub
parent 6fa2e8e3ca
commit 46a486c694
4 changed files with 351 additions and 2 deletions

View File

@@ -36,7 +36,7 @@ import { stringOrEmpty } from "./strings"
import { type GraphOrSubgraph, Subgraph } from "./subgraph/Subgraph"
import { SubgraphInput } from "./subgraph/SubgraphInput"
import { SubgraphOutput } from "./subgraph/SubgraphOutput"
import { getBoundaryLinks, groupResolvedByOutput, mapSubgraphInputsAndLinks, mapSubgraphOutputsAndLinks, multiClone, splitPositionables } from "./subgraph/subgraphUtils"
import { findUsedSubgraphIds, getBoundaryLinks, groupResolvedByOutput, mapSubgraphInputsAndLinks, mapSubgraphOutputsAndLinks, multiClone, splitPositionables } from "./subgraph/subgraphUtils"
import { Alignment, LGraphEventMode } from "./types/globalEnums"
import { getAllNestedItems } from "./utils/collections"
@@ -1674,7 +1674,14 @@ export class LGraph implements LinkNetwork, BaseLGraph, Serialisable<Serialisabl
}
if (this.isRootGraph && this._subgraphs.size) {
data.definitions = { subgraphs: [...this._subgraphs.values()].map(x => x.asSerialisable()) }
const usedSubgraphIds = findUsedSubgraphIds(this, this._subgraphs)
const usedSubgraphs = [...this._subgraphs.values()]
.filter(subgraph => usedSubgraphIds.has(subgraph.id))
.map(x => x.asSerialisable())
if (usedSubgraphs.length > 0) {
data.definitions = { subgraphs: usedSubgraphs }
}
}
this.onSerialize?.(data)

View File

@@ -1,8 +1,10 @@
import type { GraphOrSubgraph } from "./Subgraph"
import type { SubgraphInput } from "./SubgraphInput"
import type { SubgraphOutput } from "./SubgraphOutput"
import type { INodeInputSlot, INodeOutputSlot, Positionable } from "@/interfaces"
import type { LGraph } from "@/LGraph"
import type { ISerialisedNode, SerialisableLLink, SubgraphIO } from "@/types/serialisation"
import type { UUID } from "@/utils/uuid"
import { SUBGRAPH_INPUT_ID, SUBGRAPH_OUTPUT_ID } from "@/constants"
import { LGraphGroup } from "@/LGraphGroup"
@@ -339,6 +341,54 @@ export function mapSubgraphOutputsAndLinks(resolvedOutputLinks: ResolvedConnecti
return outputs
}
/**
* Collects all subgraph IDs used directly in a single graph (non-recursive).
* @param graph The graph to check for subgraph nodes
* @returns Set of subgraph IDs used in this graph
*/
export function getDirectSubgraphIds(graph: GraphOrSubgraph): Set<UUID> {
const subgraphIds = new Set<UUID>()
for (const node of graph._nodes) {
if (node.isSubgraphNode()) {
subgraphIds.add(node.type)
}
}
return subgraphIds
}
/**
* Collects all subgraph IDs referenced in a graph hierarchy using BFS.
* @param rootGraph The graph to start from
* @param subgraphRegistry Map of all available subgraphs
* @returns Set of all subgraph IDs found
*/
export function findUsedSubgraphIds(
rootGraph: GraphOrSubgraph,
subgraphRegistry: Map<UUID, GraphOrSubgraph>,
): Set<UUID> {
const usedSubgraphIds = new Set<UUID>()
const toVisit: GraphOrSubgraph[] = [rootGraph]
while (toVisit.length > 0) {
const graph = toVisit.shift()!
const directIds = getDirectSubgraphIds(graph)
for (const id of directIds) {
if (!usedSubgraphIds.has(id)) {
usedSubgraphIds.add(id)
const subgraph = subgraphRegistry.get(id)
if (subgraph) {
toVisit.push(subgraph)
}
}
}
}
return usedSubgraphIds
}
/**
* Type guard to check if a slot is a SubgraphInput.
* @param slot The slot to check