Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Nested business object depth exponentially increases the number of Root.OnPropertyChanged calls #813
This caused sever performance issues for us with a 3-Tier WPF application. The in-memory calculations took 30 seconds plus. So button click - UI blocked for 30+ seconds.
We dug and dug thinking it was the size of the business object graph or the number of calculations which are both large. However, removing chunks didn't create any substantial gains. Finally we realized our Root.OnPropertyChanged event was being raised 54 million times. Again, removing chucks didn't create any substantial gains. Further investigation we found the root cause is the depth of the object graph - up to 10 business objects. For each level down the number of Root.OnPropertyChange calls grows exponentially.
Simple business object (SimpleBO) with a Name and Depth property and itself as a child property.
Count of Root.OnPropertyChanged for each update of SimpleBO.Name at each depth:
Depth: 0 PropertyChangedCount: 7
It jumps into the billions after this.
So, now the hard part. What's the solution? My guess is this is for when the UI binds to one of the meta-state properties on a mid-level business object. Anything more?
One solution would be to not use INotifyPropertyChanged.OnPropertyChanged to communicate between business objects. That way INotifyPropertyChanged.OnPropertyChanged could be called on each BO as we traverse up the object graph BUT this would not lead to a "zig-zag" up and down the graph. However, there's fair amount of code. Does this make sense? Thoughts? Better ideas (I hope)??
Ok, I have a fix in place. Moved everything to ChildChanged. OnPropertyChanged is now only responsible for screen bindings. See the following pull request:
Depth: 0 PropertyChangedCount: 10
Just wanted to note the final approach is NOT "Moved everything to ChildChanged. OnPropertyChanged is now only responsible for screen bindings."
Rather parent business objects continue to listen to Child.INotifyPropertyChanged.OnPropertyChanged. Only created MetaPropertyChangedEventArgs which inherits from PropertyChangedEventArgs and is raised by MetaPropertyHasChanged. This way parent business objects can distinguish the problematic "MetaPropertyHasChanged" calls and stop the snowball effect.