perf: remove deep: true from 3 hot watchers to reduce reactivity overhead (#9248)

All three watchers used { deep: true } unnecessarily because their
watched sources already produce new object/array references on change,
making deep traversal redundant:

- GraphView.vue: queueStore.tasks is a computed that spreads three
  shallowRef arrays into a new array each time. TaskItemImpl instances
  are immutable (readonly fields, replaced not mutated).

- DomWidget.vue: Replaced opaque widgetState deep watcher with explicit
  property deps (pos, size, zIndex, readonly, positionOverride). During
  60 FPS pan/zoom, Vue no longer walks the entire DomWidgetState object
  graph including the markRaw widget — only 5 leaf properties are
  checked. pos and size are new array literals each frame; the rest are
  primitives.

- GraphCanvas.vue: nodeLocationProgressStates is a computed returning a
  new Record on every execution progress event (nodeProgressStates is
  replaced wholesale via WebSocket handler).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9248-perf-remove-deep-true-from-3-hot-watchers-to-reduce-reactivity-overhead-3136d73d365081278f18da5a2eef6971)
by [Unito](https://www.unito.io)

Co-authored-by: bymyself <cbyrne@comfy.org>
This commit is contained in:
John Haugeland
2026-03-13 05:55:52 -07:00
committed by GitHub
parent 07d5bd50f6
commit f4bf169b2f
2 changed files with 18 additions and 6 deletions

View File

@@ -363,7 +363,14 @@ watch(
}
)
// Update the progress of executing nodes
/**
* Propagates execution progress from the store to LiteGraph node objects
* and triggers a canvas redraw.
*
* No `deep: true` needed — `nodeLocationProgressStates` is a computed that
* returns a new `Record` object on every progress event (the underlying
* `nodeProgressStates` ref is replaced wholesale by the WebSocket handler).
*/
watch(
() =>
[executionStore.nodeLocationProgressStates, canvasStore.canvas] as const,
@@ -381,8 +388,7 @@ watch(
// Force canvas redraw to ensure progress updates are visible
canvas.setDirty(true, false)
},
{ deep: true }
}
)
// Update node slot errors for LiteGraph nodes

View File

@@ -142,11 +142,18 @@ watch(
{ immediate: true }
)
/**
* Reports task completion telemetry to Electron analytics when tasks
* transition from running to history.
*
* No `deep: true` needed — `queueStore.tasks` is a computed that spreads
* three `shallowRef` arrays into a new array on every change, and
* `TaskItemImpl` instances are immutable (replaced, never mutated).
*/
if (isDesktop) {
watch(
() => queueStore.tasks,
(newTasks, oldTasks) => {
// Report tasks that previously running but are now completed (i.e. in history)
const oldRunningTaskIds = new Set(
oldTasks.filter((task) => task.isRunning).map((task) => task.jobId)
)
@@ -161,8 +168,7 @@ if (isDesktop) {
status: task.displayStatus.toLowerCase()
})
})
},
{ deep: true }
}
)
}