Skip to content

DYN-8801 UpdateLayout Performance#16279

Merged
zeusongit merged 11 commits into
DynamoDS:masterfrom
RobertGlobant20:DYN-8801-UpdateLayout-PerformanceFinal
Jun 30, 2025
Merged

DYN-8801 UpdateLayout Performance#16279
zeusongit merged 11 commits into
DynamoDS:masterfrom
RobertGlobant20:DYN-8801-UpdateLayout-PerformanceFinal

Conversation

@RobertGlobant20

Copy link
Copy Markdown
Contributor

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.

image

Declarations

Check these if you believe they are true

  • Is documented according to the standards
  • The level of testing this PR includes is appropriate
  • User facing strings, if any, are extracted into *.resx files
  • Snapshot of UI changes, if any.
  • Changes to the API follow Semantic Versioning and are documented in the API Changes document.
  • This PR modifies some build requirements and the readme is updated
  • This PR contains no files larger than 50 MB
  • This PR introduces new feature code involve network connecting and is tested with no-network mode.

Release Notes

Reduce the number of calls to UpdateLayout (Measure - Arrange) when loading a graph

Reviewers

@zeusongit @reddyashish

FYIs

@achintyabhat

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).

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the ticket for this pull request: https://jira.autodesk.com/browse/DYN-8801

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 NodeView and NodeBorder sizes on size changes.
  • Extend NodeViewModel, WorkspaceModel, and ModelBase to 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.DefaultWidth and DefaultHeight are not defined on NodeModel; the constants live on ModelBase. This reference will not compile. Replace with ModelBase.DefaultWidth or reference the correct class.
if (ViewModel.Width > NodeModel.DefaultWidth && ViewModel.Height > NodeModel.DefaultHeight)

Comment thread src/DynamoCoreWpf/Views/Core/NodeView.xaml.cs Outdated
Comment thread src/DynamoCoreWpf/Views/Core/NodeView.xaml.cs Outdated
NodeModel.HeightBorder = value;
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

image

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
@RobertGlobant20

Copy link
Copy Markdown
Contributor Author

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.
Also a change done in this #1988 was reverted (the one using nodeBorder.ActualHeight) then we will need to re-test the functionality with my changes.

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.
@RobertGlobant20

Copy link
Copy Markdown
Contributor Author

Just updated this branch with master latest changes (due to some regressions reported that are passing for me locally).
This is the list of things that I noticed with my changes:

  1. When setting the Width and Height for NodeView all the nodes were showing the wrong size and the number of calls to LayoutUpdate() were the same so I had to do a similar procedure for the NodeView.nodeBorder (serialize the NodeBorder size and deserialize it when reading a dyn file), after this the calls to Measure() and Override() were reduced.
  2. Even with the fix from the previous point there was a lightly problem with the node Height, so noticed that there was another code updating the NodeModel Width and Height using the NodeView.Width and nodeBorder.Height so I updated the OnSizeChanged method to use NodeView.Width and NodeView.Height but this generated a problem with the connector showing in a different location, so I had to apply another fix for fixing the connectors problem
  3. There were 3 tests failing so i did several changes in code and in the tests for fixing those regressions.
  4. By setting the NodeView size and the NodeBorder size the calls to Measure and Override were reduced (from 6 or 7 in total to 2) when we have several nodes not connected but for big graphs like Manekin-0.50 and Hotel Calculator the number of calls were reduced for a few calls (like 200 or 300 less in a total of several thousands).

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

@QilongTang

Copy link
Copy Markdown
Contributor

@zeusongit by looking at the history of this PR, seems @RobertGlobant20 is recommending merging and testing this. What do you think?

@zeusongit

Copy link
Copy Markdown
Contributor

@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

@zeusongit

Copy link
Copy Markdown
Contributor

Merging as per discussion

@zeusongit zeusongit merged commit 39e17d8 into DynamoDS:master Jun 30, 2025
26 of 28 checks passed
RobertGlobant20 added a commit to RobertGlobant20/Dynamo that referenced this pull request Jul 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants