Runtime Optimizations

Discuss issues pertaining to the Creature Animation Editor here.
Post Reply
pg_interactive
Posts: 16
Joined: Thu Feb 22, 2018 2:42 pm

Runtime Optimizations

Post by pg_interactive » Sun Jul 22, 2018 1:54 pm

May i suggest a runtime optimization for the Creature Unity Runtimes, specifically the garbage creation and collection optimization which causes in-engine stutter when garbage is collected.

Use Unity Editor / Window / Profiler / Deep Profile = Toggle ON when testing for Garbage Generation.


What creates garbage in Creature Unity Runtimes?

CAUSE:
Heaviest garbage generation occurs due to per-frame usage of the "new" keyword.

EXAMPLE:

Code: Select all

Example 1A)
MeshBone::computeWorldDeltaTransforms
XnaGeometry.Vector3 cur_tangent = new XnaGeometry.Vector3(calc.Item1.X, calc.Item1.Y, 0);

Exmaple 1B)
MeshBone::computeDirs
return new Tuple<XnaGeometry.Vector4, XnaGeometry.Vector4> (tangent, normal);

Example 1C)
CreatureManager::RunCreature
public void RunCreature()
{
 ...
     for (int i = 0; i < 2; i++)
     {
          ...
          foreach (var cur_bone_packet in bones_map)
          {
               XnaGeometry.Vector4 cur_bone_start_pt = new XnaGeometry.Vector4(0, 0, 0, 0);
               XnaGeometry.Vector4 cur_bone_end_pt = new XnaGeometry.Vector4(0, 0, 0, 0);
          }
     }
 ...
}
SOLUTION:
Instance caching. Cache and reuse the object instances that cause garbage (for example cache and reuse your custom Tuple and XnaGeometry.Vector4 instances).

COST
The current cost of garbage per frame due to using uncached instances in a simple example we've used is 26.3kB. This is significant, and can certainly be brought down to 0kB per frame. A simple glance through the code will reveal that using metada for events for example, will further add to this number (usage of foreach on all available frame_callback(s) on each frame [sidenote: using the tryTrigger could be certainly replaced with a better solution]; for now, instead of foreach, you could just use for).

Don't use foreach, and if you must, use IEnumerator with it. Using for() cycle is GC-free. There are other things to avoid like Delegates (create garbage during subscribe/unsubscribe/call), Coroutines (create garbage when called), runtime Serialization/Deserialization, object creation (described above)/Destruction, using dynamic strings (use StringBuilder instead, if you must), and others, all create garbage. Use structs instead of classes, where applicable (they are created in Stack rather than on Heap, just like other value-types - meaning they are GC-free [cause no garbage]). Also, if you find that you need multiple instances of the same object each frame, you might want to create ObjectPool for such instances.

Bottom line, use Profiler + Deep Profile to profile your code and especially optimize the code inside loops/nested loops. You can easily see the ms/kb cost of per-frame GC in the Profiler, and focus on the heavy hitters first. Also, in C# Unity, Profiler.BeginSample(“SampleName”) / Profiler.EndSample() might help to locate the exact line of code where the garbage is being created.

I've seen other animation solutions for Unity run with 0GC-hit per frame, I'm sure You can too! Best wishes, hope this can help to make Creature better.
Last edited by pg_interactive on Sun Jul 22, 2018 6:45 pm, edited 1 time in total.

chong
Posts: 835
Joined: Thu Feb 19, 2015 2:21 am

Re: Runtime Optimizations

Post by chong » Sun Jul 22, 2018 4:29 pm

Hello,

Thanks for the very useful + important tips! I will look into the Unity runtime optimizations when I get the cycles. Right now the focus is on rolling out the next big Creature update, and then yes the focus will shift back to maintenance, bug fixes and runtime optimizations/improvements.

Btw, if you are using the regular Unity runtimes, you can try enabling point caching. It is a lot faster and bypasses the posing engine ( assuming you are not doing custom runtime procedural bone posing ). Having said that, yes, those tips you provided will be used a guide for runtime optimization.

Cheers

pg_interactive
Posts: 16
Joined: Thu Feb 22, 2018 2:42 pm

Re: Runtime Optimizations

Post by pg_interactive » Sun Jul 22, 2018 6:25 pm

chong wrote:
Sun Jul 22, 2018 4:29 pm
you can try enabling point caching. It is a lot faster and bypasses the posing engine
Thanks, this is a great suggestion!

Post Reply