This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
When I have about 800+ nodes in my diagram, the TreeLayoutAlgorithm (and any UI rendering that takes place after this) locks up the UI thread considerably. Anyway to call TLA.Run() on a background thread/task? I started this project a long time ago and am looking to optimize. I am using a custom CollapsableNode with an "IsVisible" property that Jason recommended on this thread: http://www.mindscapehq.com/forums/thread/451392 I know the TreeLayoutAlgorithm doesn't look at my IsVisible property so I could modify the algorithm to ignore any hidden nodes in my diagram. But if the user wants to "Expand All" and show the entire diagram, TLA.Run() is very slow and locks the UI thread because I am not sure if an async call is possible. Looking for any advice on freeing up the UI thread. |
|
|
I've seen many posts about limiting the ViewPort to allow virtualization to speed things up, can this help? Any tips? |
|
|
Hello, If you are displaying the entire 800 node diagram within the visible viewport, then this will certainly be slow. One thing you could do is to try implementing different node templates for different levels of detail. When the digram is zoomed out far to display all the nodes, you could use a low level of detail template for each node which could just be a colored rectangle. Then zooming in a certain amount could switch to using your normal node templates. Otherwise, setting the viewport to show only part of the diagram will cause only the visible nodes to be created and rendered which can ease off the pressure on the UI thread. -Jason Fauchelle |
|
|
Ok so let me ask about the 1st time I load my diagram. I only have 10 nodes visible and the rest are set to IsVisible = false; (based on the example I linked above and started my project from). Therefore, SetViewport has never had any affect on my load time. TLA.Run() consistently takes about 13 seconds with 800 nodes, and only the top 10 visible. The TLA algorithm does not take the custom IsVisible and IsExpanded properties into account, so am I on the right track by thinking I need to alter this algorithm to skip over Nodes that are not visible and Expanded? |
|
|
Hello, I am not sure why it would be taking that long. I created an 800 node tree diagram with all nodes visible (but not fitting within the viewport). The algorithm completes in 2 seconds. This should mean that you don't need to create a custom algorithm, but it doesn't answer why your diagram takes so long to complete. Would you be able to send a simplified repro project so I can look into this further? -Jason Fauchelle |
|
|
Thanks Jason, sent you a repro project. |
|
|
Hi Chris, Thanks for sending the project. I think the problem here is that before you run the algorithm, all the nodes are positioned within the viewport. Even when your nodes are invisible, the UI elements to visualize them still get created. This is because the DiagramSurface does not know about your model, and doesn't know that nodes are invisible until they have been created, templated and then had the trigger result in it being visually collapsed. Node visibility is something that we should really include in the product to improve this, though we don't have time to implement this right now. The reason why I had this working quickly at my end is I initially position all the nodes in a straight line so that only a handful of them were within the viewport. Then the diagram is able to load faster, and the TLA runs faster. I tried to do this in your repro project but couldn't quite get it to work. Could you have a look at doing something like this to improve the performance? Thanks for pointing out that you are using 2.0 node templates as this will be impacting performance. Your current node templates contain all the editing tools like size, mover and connection point thumbs. These are all being loaded when all your nodes (visible or not) are rendered. 3.0 has two node templates, an editable one containing all the editors, and a visual one that only displays the NodeTemplate. This speeds up rendering a lot by only creating the editors when a node is selected, or the mouse is over a node. I've attached the latest template file which you could use to replace your current templates. One way to do level-of-detail template switching is to use a trigger on the node template, binding to the Zoom property of the DiagramSurface, and using a custom converter to signal that the zoom is less or greater than some zoom threshold. I have not tried this fully myself, but know that a few of our customer have used this technique successfully. Hope this all helps you to boost the performance. Please let me know if you have any questions. -Jason Fauchelle |
|
|
So what you said made sense at first because I was loading the diagram collapsed, only showing the 1st two rows (about 10 nodes) and the rest were collapsed/hidden underneath them. so this, in effect, had all 800 diagram nodes in the viewport. So I changed my example to load all nodes expanded and all visible with the Viewport still set to just the size of my screen but it still takes over 10 seconds to run TLA.Run(). I see no difference at all. What's strange is after it loads and I scroll left or right, it seems like the entire diagram visual was already loaded. I mean, it scrolls perfectly, I don't see any "Loading" of new visuals. Would that happen, or am I not understanding how you load the Viewport as it is scrolled? So just to make sure I'm following the right order of things: I build my DiagramModel on a background thread. Then on the UI thread, I set my Viewport (for now, just to the size of my screen), Assign my model to my diagram surface, then call TLA.Run()? And the Viewport takes standard screen coordinates, right? so setting it to a Rect of x=0->1920 and y=0-> 1080 should set it to the size of my screen? |
|
|
Hi Chris, Once you assign the Diagram model to the DiagramSurface, the DiagramSurface will create any node UI elements that are within the viewport. So it sounds like you still might have all the nodes within the viewport at the time you set the diagram to the surface. I would recommend either running the algorithm before setting the DiagramSurface diagram, or at least position all the nodes in a straight line or some other configuration where they are not likely to be within the viewport when you initially pass the diagram to the view. The viewport is actually a logical rectangle - using the same logical plane that nodes are positioned and sized on. Say you have a node at position 0,0 and another at position 100,100, if you then set the viewport to 0,0,100,100 it would zoom and pan to roughly include those 2 nodes in the corners. Note that the actually viewport that gets used will be slightly different to what you specify in order to maintain the aspect ratio. For now, maybe don't set the viewport, then see what the diagram looks like on first load, and then work out a suitable initial viewport if necessary. By default, the viewport should initially be at "100% zoom" which should mean a single logical unit in the diagram equates to a single pixel on the screen which I think is what you want. (A node 100 units wide would be rendered as 100 pixels). If you have Snoop (A WPF app visual tree browser tool) then you could use it to examine the DiagramSurface contents straight after the load. Based on the number of DiagramNodeElements within the DiagramSurface visual tree, you'll be able to see if virtualization is working correctly. (May as well try my first suggestion above before needing to try this). Hope that helps, please let me know if you have questions about any of this. -Jason Fauchelle |
|
|
Your 1st suggestion was easy to attempt so I did. When I run TLA.Run on my DiagramModel, before Assigning it to the DiagramSurface, it runs incredibly fast, and all of the Nodes end up in the correct place on the diagram, but none of the connectors are connected. They are just kind of curled up on the top of the Diagram. If I put TLA.Run() back to taking the Model after it has been assign the the Surface, it looks correct but performance is slow as before. I think we are on to something here... but any idea why the connectors aren't rendering correctly when I run TLA on just the model, before assigning to the Surface? EDIT: Forgot to mention that after doing the 1st suggestion of running TLA on the Model before assigning it to the Diagram, I can now see that the Viewport is working... because when I scroll around, I can see the new visuals being loaded in. Very nice and performance is very acceptable. Just need to fix these connectors. |
|
|
Jason - Think I have it fixed. I thought I could be sneaky by running TLA.Run on my background thread since I was now running it on just my DiagramModel and had not bound it to the DiagramSurface (UI) yet. When I did this, the connectors were messed up. If I put TLA to run on my Model, but pushed that to the UI thread, it now renders correctly and is VERY fast. So lesson learned here.... Build Diagram Model on background thread, run Layout Algorithm on the model on the UI thread, THEN bind it to the Diagram Surface. This just cut 8 seconds off my load time. Where's the donate button????? =D |
|
|
Hi Chris, Excellent, great to hear you've solved the problem. The messed up connections when running TLA on a background thread sounds like something we could improve. I've noted this down as something to look into for a future version. -Jason Fauchelle |
|
|
I'd like to add one more note in case this helps anyone with display performance of large diagrams: I get this large performance boost if I load my 800 node diagram expanded, with all nodes showing, then immediately call my "Collapse All" method which shrinks the diagram back up to the top 2 rows after the diagram has finished rendering. By loading expanded, I believe I get the benefit of the Viewport not loading all the visuals. My CollapseAll method then runs so fast I visually cannot see it happening and the diagram is loaded in the original state I wanted, with just the top 2 rows of nodes showing. I also get the added benefit of my "Expand All" button running quickly now too. Previously, when I would load the entire diagram in a collapsed state, where all 800 nodes were hidden, but still inside the viewport, not only would the diagram load slower, but the 1st time I would click on my "Expand All" button, there would be a big delay. Not the case anymore. |
|