EMSUSD-3880 Optimizes Multi-stage loading performance#4660
Conversation
There was a problem hiding this comment.
Pull request overview
This PR optimizes Layer Editor responsiveness during bulk USD stage loads by coalescing high-frequency session notifications and removing repeated full-DAG scans, reducing per-stage UI rebuild work to at most once per event-loop turn.
Changes:
- Coalesces
StageSelectorWidget::updateFromSessionStateso bursts ofstageListChangedSignaltrigger a single dropdown rebuild (last requested selection wins). - Coalesces
LayerTreeView::updateFromSessionStateso stage list bursts trigger a single cached-state refresh per event-loop turn. - Replaces repeated
SessionState::allStages()(full Maya DAG scan) lookups in stage selection handlers with a local combo-box id lookup (comboIndexById).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| lib/usd/ui/layerEditor/stageSelectorWidget.h | Adds coalescing state and an idle-coalesced update method to reduce per-stage UI rebuilds. |
| lib/usd/ui/layerEditor/stageSelectorWidget.cpp | Implements idle coalescing and replaces DAG-scan lookups with combo-based id lookup. |
| lib/usd/ui/layerEditor/layerTreeView.h | Adds an idle-coalesced refresh method and pending flag for stage-list bursts. |
| lib/usd/ui/layerEditor/layerTreeView.cpp | Implements idle coalescing for stage-list refreshes to avoid per-stage full rescans. |
| lib/usd/ui/layerEditor/layerTreeModel.h | Extends idle rebuild API to accumulate lock-state refresh requests. |
| lib/usd/ui/layerEditor/layerTreeModel.cpp | Coalesces rebuild requests and threads lock-state refresh through the idle rebuild path. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| if (it != stages.end()) { | ||
| return std::distance(stages.begin(), it); | ||
| for (int i = 0, count = dropDown->count(); i < count; ++i) { |
There was a problem hiding this comment.
Do we need to guard against input dropDown == nullptr?
There was a problem hiding this comment.
Good suggestion. It seems that dropdown is only created in a constructor once and never reset (not even in the destructor). So at all the callers' location the dropDown is guaranteed non-null for the widget's entire lifetime.
I could still add this if it's blocking this PR, or take a note and improve it later.
if (!dropDown)
return -1;
seando-adsk
left a comment
There was a problem hiding this comment.
Good work - thanks.
EMSUSD-3880 Optimizes Multi-stage loading performance
While the Layer Editor is open, loading many USD stages at once was O(N^2): each per-stage notification (stage set, current-stage change, proxy add/remove, selection change) triggered a full model rebuild, combo-box rebuild, or a full-DAG-scan allStages() lookup — once per stage. This coalesces those reactions and removes the per-stage scans, all within the Layer Editor.
Changes:
LayerTreeModel::sessionStageChangednow defers through the coalescedrebuildModelOnIdleinstead of rebuilding synchronously on every stagechange; the lock-state refresh is preserved by threading it through the idle rebuild (rebuildModelOnIdle now takes a refreshLockState arg
alongside dev's dataChanged arg).
StageSelectorWidget::updateFromSessionStateis now coalesced: a burst ofstageListChangedSignalnotifications collapses into a single combo rebuild (last requested selection wins). LayerTreeView::updateFromSessionState is likewise coalesced into a single refresh per event-loop turn.allStages()(full Maya DAG scan) index lookups inselectionChanged/sessionStageChanged/stageRenamed/stageResetwith a local combo lookup by id (comboIndexById), since the combo already holds the stage entries. Removed the now-unusedgetEntryIndexByIdhelpers.Impact (500-stage bulk load, Layer Editor open): ~44s -> ~12s (~3.5x);
Layer-Editor self-time ~31s -> ~65ms. The remaining cost is core UsdStageMap / ProxyShapeHandler quadratic work, independent of the Layer Editor, tracked separately.