Debug character rig performance

When a rig is being worked on over a few years, it can easily get slower and slower without noticing it right away! This is a pain for anyone working with it all day long, especially with Maya…

But you don’t want to optimize something for ages and then realize it actually didnt improve the fps at all. We are using a modular scripted rig so optimize it is quite easy, just have to know where to start :):

What are your tips for debugging the root of the problem?

Cheers
Johan

well the first thing to do is write a proper performance tester rather than relying on the FPS Hud in Maya. All we do is force on the play-all options, set an xtimer going, play though the timerange and calcualte the actual time taken. That’s a good start to test speed up’s.

There is the heat map in the Hypershade that they added in 2009, but I’ve never really had any truely useful data out of it, other than knowing that the skinning is the heaviest node, no suprise there.

History on skinned meshes is often the main culpret.

Well firstly consider offering multiple resolutions for animators to work with, preferably one with no skinned meshes too. For gross body motion the animators have no reason to see the skinned mesh until they do a capture. (especially on a game rig which most likely is not utilizing any other deformers).
If you really got some mad development time on your hands then write an real time shader that will do the skin deformation for you instead of the skin cluster for preview purposes.

Get rid of all expressions in your rig!
If you are using custom nodes then start looking there first for optimization.
Consider limiting number of utility nodes too. If you need to multiply 3 values there is no need to have 3 multiplyDivide nodes.

Prune all deformers.

Simplify. I often would go through the systems in my rig and find I can do it in a different way and be able to get rid of some 100 constraints.

Lots of good ideas so far.

Definitely try to replace expressions with something else and work on cleaning up the node network(s). Scripted rig setups, depending on how they were built, will often add loads of stuff you don’t really need and can be simplified quite a bit.

If it’s real messy, maybe do a node count on the rig and set a goal to try to get it down to a certain number.

Just wanted to echo Jay and Shadow on doing a clean up pass over the rig to simplify connections and limit overall number of nodes.

The cleaner and more straightforward you can make the rig, the faster it will run, but don’t simplify if it looses a rig feature you need or if in trying to make it fast, you make it hard/impossible to debug and fix for another artist or your self 6 months later.

I try and keep this Einstien paraphrased quote “Make things as simple as possible, but not simpler.” in mind when designing out a rig.

*great tip on the “If you need to multiply 3 values there is no need to have 3 multiplyDivide nodes.”

And of course, limit the number of key framed channels on the rig, don’t let animators set keys on values they shouldn’t and track down any cycle errors and remove them , I find peoples files with this happening and they never fix it and it can cause slowdowns and evaluation issues.

*Another quick thing I have noticed, speed check for moving controls around etc. but forget to test rig speed with full set of key frames on all controls while playing back… as the animator actually would be useing it.

Anyway, great thread because unless your in Motionbuilder or Reflex, your animators are always goign to want faster,faster,faster.

I always use proper (well… as proper as you can in a scripting language) timestamping and compare the milliseconds used.

I don’t know how to achieve this in Maya, but in theory you can easily start by just storing the initial timestamp in milliseconds and putting a lot of debug print statements to various parts of the rig code where you list which stage started, when it ended how many milliseconds it took. Otherwise you’ll end up with trying to optimize something that wasn’t slow to begin with.

Doing anything based on the viewport FPS meter is just wrong wrong wrong.

E.g,
Say you have a very slow scene which runs at 10 FPS. Thus, you use 100ms per frame to render. You find some constant slow query which always takes 25ms per frame (like some lookup or something). You optimize that away and get the time down to 75ms per frame. However, your FPS counter only shows the optimized scene runs at 13.3 FPS.

However, if another scene was previously running at 25 FPS (thus, 40ms per frame), but you managed to use the same optimization there and gain another 25ms per frame saving - thus spending 15ms per frame you’ve managed to bump the framerate to 66 FPS.

Now, if you tell your users you got the framerate from 10 to 13.3 they’ll go… Oh… Keep at it.

But if you tell your users you got the framerate from 25 to 66 they’ll say you walk on water.

It’s amazing how many people (even programmers optimizing game code) get it wrong and just look at FPS numbers when they should ALWAYS be looking at milliseconds spent when seeing if an optimization made any sense.

SamiV.

you can use the maya’s new heat map feature too.
With this tool, you will have a representation of the more heavy nodes in the DG.
This tool is in the Hypergraph menu option>heat map display

pijiaoyou1978iljpxynaheecxhcxnbtrxieliangdang4994xcfdz

Lots of good replies here! Digging even deeper…
How can you compare the performance over time, when switching computers, system etc? Evaluating num operations instead of seconds?

When running the dgtimer command in Maya, lots of data is returned. But what is most useful? Would love to have a nice excel-chart keeping track of how the rig is evolving over time.

Cheers, Johan

SECTION 1: Global timing information:

1.1 Global timing modes:
Global timing is currently : OFF
Global tracing is currently: OFF

1.2 Process time since last reset:
Elapsed real time : 5.89115 sec
Elapsed user time : 0 sec
Elapsed system time : 0 sec

1.3 Summary of each metric for all nodes:
Real time in callbacks : 2.35164 sec [6563 operations]
Real time in compute : 1.1559 sec [189546 operations]
Real time in dirty propagation : 0.925824 sec [249988 operations]
Real time in drawing : 0.12967 sec [31512 operations]
Real time fetching data from plugs : 0.37642 sec [408916 operations]

1.5 Breakdown of select metrics in greater detail:
Breakdown of “callback” metric in greater detail:
Real time in callbacks registered via API : 0 sec [0 operations]
Real time in callbacks NOT registered via API: 2.35164 sec [6563 operations]
Breakdown of “compute” metric in greater detail:
Real time in compute invoked from callback : 0 sec [0 operations]
Real time in compute not invoked via callback: 1.1559 sec [189546 operations]
Plug caching performance:
Ratio of computes to fetches : 0.4635
Ratio of time in compute to (compute + fetch): 0.7543

Prune membership sets… especially important if you are loading a lot of PSD shapes.