I am trying to optimize performance for my plugin. My plugin involves robot motion planning and sometimes the frame rate slows down for seemingly trivial things like using Draw2DText() in a loop that runs about 25-30 times. If I remove this drawing loop, the performance almost doubles. In the image below, DrawPassNumbers() has this for loop that runs about 30 times and calls e.Display.Draw2dText()
I was wondering to offload a lot of heavy drawing tasks like the above mentioned loop and drawing of several heavy meshes and breps to their own display conduits. In the above image, each circled draw call could be its own conduit.
I was wondering if anyone can shed some light on performance differences between drawing everything in a single display conduit or having multiple display conduits for different plugin items.
As far as we can tell this is going to be on the order of O(n^2) depending on the number of objects and passes there are. And then that is inside yet another loop. Certainly not a very efficient way to draw anything.
A lot of your drawing is based on the states of certain flags and settings. It seems like you should have a pre-draw pass that adds the things that need to draw into a series of buckets (for lack of better term). then just dump (i.e. draw) the buckets in the draw routine. If the state changes for any of the criteria above, then rebuild the buckets.
By doing this, the buckets only contain what needs to be drawn, which can change based on UI and settings changes. But that only happens once, when the change occurs, and not done every time in a draw routine.
Does that make sense?
Also, splitting your single conduit into multiple isn’t going to help with speed.
Thanks for the reply. I am quite new when it comes to computer graphics, so I learnt something new today
Yes, a lot of my drawing is based on UI toggles that the user can switch to view more or less information about the robot motion and simulation. Over time, it has gotten a bit bloated with the amount of geometries to be drawn (hence the need to optimize).
I think I get the general idea of what you mean. I am unclear on the “buckets” part. By buckets, do you mean that I prepare a list of all the geometries to be drawn (when any UI toggle is changed) and then just have a single loop inside the display conduit draw method to draw the list ?
The general idea is to eliminate the three nested loops in your draw process, by offloading all of that processing into a non-drawing portion of your code. Yes, “bucket” is just term we use to store “things”, but they are essentially just lists.
Since you have 5 conditions in your inner loop, that means you probably need 5 separate lists, since each condition is doing/drawing something different. Then in your draw routine, you just iterate each list, calling the appropriate draw action based on the list you’re iterating.
…populate those lists accordingly one time, and then only draw what’s in those lists within your draw routine… If/when a user makes a change to something, then repopulate the lists again…only once. That way you’re only going through your three nested loops one time, and only when something changes.
Note: Make sure you clear the lists each time you go to populate them, otherwise they can grow out of control, and contain duplicates.
Yes that makes sense. I think get the idea now and will refactor my code to offload calculations and the nested loops there. Thank you so much for this!
Update: After refactoring my code, I am able to save up to 5ms of frame time in certain scenarios! Which considering my 16-33ms target budget, its quite a bit! Also, I found a big culprit that consumed quite a bit of my frame time, I was using DisplayPipeline.DrawArrowHead() inside the DrawRobotFrames() method. There would quite a bit of arrow heads considering the number target positions of robot would also be very high.
Snippet from my DrawRobotFrames() method:
After removing DrawArrowHead(), the performance almost doubled! This happens even after I removed the nested loops. Any idea why DrawArrowHead is so performance intensive and are there any “cheaper” alternatives to it?