mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-09-06 08:16:03 +00:00
performance fix: limited doc similarity check to 50 docs for now, memory leak fix (cleanup deleted nodes), and updating node/edge at the same time instead of one after another.
This commit is contained in:
parent
db0f74110a
commit
e1116726c0
2 changed files with 38 additions and 12 deletions
|
|
@ -114,16 +114,17 @@ export function useForceSimulation(
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [enabled])
|
||||
|
||||
// Update simulation nodes when they change
|
||||
// Update simulation nodes and edges together to prevent race conditions
|
||||
useEffect(() => {
|
||||
if (simulationRef.current && nodes.length > 0) {
|
||||
if (!simulationRef.current) return
|
||||
|
||||
// Update nodes
|
||||
if (nodes.length > 0) {
|
||||
simulationRef.current.nodes(nodes)
|
||||
}
|
||||
}, [nodes])
|
||||
|
||||
// Update simulation edges when they change
|
||||
useEffect(() => {
|
||||
if (simulationRef.current && edges.length > 0) {
|
||||
// Update edges
|
||||
if (edges.length > 0) {
|
||||
const linkForce = simulationRef.current.force<
|
||||
d3.ForceLink<GraphNode, GraphEdge>
|
||||
>("link")
|
||||
|
|
@ -131,7 +132,7 @@ export function useForceSimulation(
|
|||
linkForce.links(edges)
|
||||
}
|
||||
}
|
||||
}, [edges])
|
||||
}, [nodes, edges])
|
||||
|
||||
// Reheat simulation (called on drag start)
|
||||
const reheat = useCallback(() => {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import {
|
|||
getConnectionVisualProps,
|
||||
getMagicalConnectionColor,
|
||||
} from "@/lib/similarity"
|
||||
import { useMemo, useRef } from "react"
|
||||
import { useMemo, useRef, useEffect } from "react"
|
||||
import { colors, LAYOUT_CONSTANTS } from "@/constants"
|
||||
import type {
|
||||
DocumentsResponse,
|
||||
|
|
@ -26,6 +26,27 @@ export function useGraphData(
|
|||
// Cache nodes to preserve d3-force mutations (x, y, vx, vy, fx, fy)
|
||||
const nodeCache = useRef<Map<string, GraphNode>>(new Map())
|
||||
|
||||
// Cleanup nodeCache to prevent memory leak
|
||||
useEffect(() => {
|
||||
if (!data?.documents) return
|
||||
|
||||
// Build set of current node IDs
|
||||
const currentNodeIds = new Set<string>()
|
||||
data.documents.forEach((doc) => {
|
||||
currentNodeIds.add(doc.id)
|
||||
doc.memoryEntries.forEach((mem) => {
|
||||
currentNodeIds.add(`${mem.id}`)
|
||||
})
|
||||
})
|
||||
|
||||
// Remove stale nodes from cache
|
||||
for (const [id] of nodeCache.current.entries()) {
|
||||
if (!currentNodeIds.has(id)) {
|
||||
nodeCache.current.delete(id)
|
||||
}
|
||||
}
|
||||
}, [data, selectedSpace])
|
||||
|
||||
return useMemo(() => {
|
||||
if (!data?.documents) return { nodes: [], edges: [] }
|
||||
|
||||
|
|
@ -296,12 +317,16 @@ export function useGraphData(
|
|||
})
|
||||
|
||||
// Document-to-document similarity edges
|
||||
for (let i = 0; i < filteredDocuments.length; i++) {
|
||||
const docI = filteredDocuments[i]
|
||||
// Performance optimization: limit comparisons to prevent O(n²) scaling issues
|
||||
const MAX_DOCS_FOR_SIMILARITY = 50
|
||||
const docsToCompare = filteredDocuments.slice(0, MAX_DOCS_FOR_SIMILARITY)
|
||||
|
||||
for (let i = 0; i < docsToCompare.length; i++) {
|
||||
const docI = docsToCompare[i]
|
||||
if (!docI) continue
|
||||
|
||||
for (let j = i + 1; j < filteredDocuments.length; j++) {
|
||||
const docJ = filteredDocuments[j]
|
||||
for (let j = i + 1; j < docsToCompare.length; j++) {
|
||||
const docJ = docsToCompare[j]
|
||||
if (!docJ) continue
|
||||
|
||||
const sim = calculateSemanticSimilarity(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue