DYN-8801 UpdateLayout Performance#16279
Conversation
I've added the functionality of serialize into the dyn file the NodeView.Width and NodeView.Height (this values will be set on the NodeView.SizeChanged event) also when loading the graph the Width and Height will be deserialized. Also added the functionality that we opening the graph, the Width and Height will be set to elements in the NodeView to avoid extra calls to MeasureOverride() and ArrangeOverride() this will produce some performance improvements avoiding calls to UpdateLayout(). Finally I modified the PublicAPI.Unshipped adding the new properties for Width and Height.
Added functionality for serialize/deserialize the NodeBorder.Width and NodeBorder.Height. Also fixed some comments And finally I've removed some code in OnSizeChanged method due that was setting the NodeView.Height incorrectly (using nodeBorder.Height).
There was a problem hiding this comment.
See the ticket for this pull request: https://jira.autodesk.com/browse/DYN-8801
There was a problem hiding this comment.
Pull Request Overview
This PR introduces serialization of node and border dimensions to reduce redundant Measure/Arrange calls during graph loading, improving layout performance.
- Capture and store
NodeViewandNodeBordersizes on size changes. - Extend
NodeViewModel,WorkspaceModel, andModelBaseto include width/height and border dimensions. - Apply deserialized dimensions when loading graphs and update PublicAPI.
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| NodeView.xaml.cs | Added size‐changed handlers and restored control sizes on load |
| NodeViewModel.cs | Added serializable Width, Height, WidthBorder, HeightBorder |
| PublicAPI.Unshipped.txt | Exposed new WidthBorder/HeightBorder API entries |
| WorkspaceModel.cs | Persisted and loaded dimension data in ExtraNodeViewInfo |
| ModelBase.cs | Introduced default constants and border dimension properties |
Comments suppressed due to low confidence (3)
src/DynamoCore/Graph/ModelBase.cs:195
- [nitpick] The summary comment contains stray text (
Add commentMore actions). Update the XML doc to a clear description or remove the placeholder.
/// <summary>Add commentMore actions
src/DynamoCore/Graph/ModelBase.cs:196
- [nitpick] This doc refers to the object width but the property is
WidthBorder. Please correct the summary to describe it as the border width.
/// The width of the object.
src/DynamoCoreWpf/Views/Core/NodeView.xaml.cs:1623
NodeModel.DefaultWidthandDefaultHeightare not defined onNodeModel; the constants live onModelBase. This reference will not compile. Replace withModelBase.DefaultWidthor reference the correct class.
if (ViewModel.Width > NodeModel.DefaultWidth && ViewModel.Height > NodeModel.DefaultHeight)
Fixing API missing declarations
Fixes Suggested by Copilot
Fixing API missing declarations
| NodeModel.HeightBorder = value; | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Why do we need this extra dimension for borders? Can't we calculate borders based on node height and width? How and when are these 2 different?
There was a problem hiding this comment.
The current nodeBorder is a WPF Border element added from row=1 to 5, column = 0 to 3 (NodeView has in total 6 rows and 3 columns) so based in that usually WPF Grids starts from row=0 you will notice by seeing the image below that the NodeView.Width, NodeView.Height (in green color) will not match NodeBorder.Width and NodeBorder.Height (the red rectangle), remember the nodeBorder is auto-calculated based in the content of row 1 to 5 and column 0 to 3.
Then when I was trying to reduce the calls to Measure() and Arrange() noticed that setting The NodeView size and setting the NodeBorder size reduced the total calls from 7 to 1 (due that probably when WPF is rendering the nodeBorder is increasing size several times due to the controls added in those specific rows, columns, so setting the size will avoid the extra calls to Measure).
One possible solution for not serializing the NodeBorder size could be setting the NodeBorder localtion from row 0 to 5 and column 0 to 3 but we will need to do several changes in NodeView.xaml (now that everything is in code behind in NodeView.xaml.cs) like Collapsing the customNodeBorders (instead of hiding them like currently is happening) and we will need to do testing in several nodes and custom nodes.
Fixing 2 tests failing
The WatchNodeWithBadSize() tests is checking the Watch node width, height against the default values but they were not assigned, so in this fix I'm assigning the default size values and now the test is passing.
re-triggering the jobs
|
For this PR I have noticed that when loading a graph which has connectors sometimes connectors are shown in a wrong position, then I need to test this case. |
When loading graphs were showing the connectors in a different location, then with this fix (calling ViewModel.SetModelSizeCommand.Execute(size);) is setting the connectors in the right place.
|
Just updated this branch with master latest changes (due to some regressions reported that are passing for me locally).
Base on the previous we should continue testing the appeareance of several nodes and check that the connectors and node size looks good also we should continue doing performance comparison in large graphs to see if is worthed to merge this PR or not. FYI: @zeusongit @reddyashish |
|
@zeusongit by looking at the history of this PR, seems @RobertGlobant20 is recommending merging and testing this. What do you think? |
@QilongTang I would recommend/like to test this and then merge it after comparison |
|
Merging as per discussion |
This reverts commit 39e17d8.

Purpose
Reduce the number of calls to UpdateLayout (Measure - Arrange) when loading a graph
I've added the functionality of serialize into the dyn file the NodeView.Width, NodeView.Height, NodeBorder.Width and NodeBorder.Height (this values will be set on the NodeView.SizeChanged event and NodeBorder.SizeChanged event) also when loading the graph the Width and Height will be deserialized for both properties.
Also added the functionality that we opening the graph, the Width and Height for both elements will be set to avoid extra calls to MeasureOverride() and ArrangeOverride() this will produce some performance improvements avoiding calls to UpdateLayout().
Finally I modified the PublicAPI.Unshipped adding the new properties for Width and Height.
Important Considerations:
This change only will work with new graphs (if is an old graph we need to re-saved or use File -> Save As for creating a new dyn file) due that we need the Width and Height for both elements stored in the dyn file.
Here you can see the result got before/after my changes (when testing with the graph Manekin-0.50):
For getting the number of calls to Measure() and Arrange() I added the methods NodeView.ArrangeOverride() and NodeView.MeasureOverrride() and add code for logging in a txt file the calls to each one (I did this for the master branch and for my feature branch), the loading time was calculated manually with the Clock app and interacting with Dynamo manually.
Declarations
Check these if you believe they are true
*.resxfilesRelease Notes
Reduce the number of calls to UpdateLayout (Measure - Arrange) when loading a graph
Reviewers
@zeusongit @reddyashish
FYIs
@achintyabhat