Optimizing memory usage, part 1: efficient step animation, using component system in X3D nodes (no interfaces), less memory used by sprite sheets

Posted on

Lots of sprite sheets with lots of animations

Nudged by the report of high memory usage I want to seriously optimize memory usage of CGE. Right now X3D nodes cost too much in memory — which limits some use-cases (when spawning a lot of TCastleScenes would be the most natural solution), and it affects both loading and runtime performance (as loading is slower when you need to clone/initialize more memory, and performance is slow when the cache is underutilized).

A first wave of improvements has already landed in the engine. A 2nd wave is in progress — it depends on remaking how all X3D nodes are set up, so it’s a big rework (but it was a long time coming).

Things done now:

  1. We now have an efficient step interpolation mode (see TInterpolation), used automatically by sprite sheets and glTF models with step animation.

    While “step” interpolation was possible previously, but it was (ab)using the linear interpolation calculation, by duplicating keys. This was wasting both memory (2x data needed) and time (doing useless lerp operations).

  2. We have simplified our X3D nodes inheritance. We use now TNodeFunctionality (a simple component system inside X3D nodes) with some descendants like TTimeDependentFunctionality and TTransformFunctionality. We no longer use Pascal interfaces for them. There are actually 2 reasons for it:

    1. In some cases, we really wanted to share implementation, not just API. So interfaces were never a proper tool.

      In effect our new TTimeDependentFunctionality is a much simplified and more natural old TInternalTimeDependentHandler, the new concept just fits our needs better.

    2. I never really grew to like COM interfaces. In FPC/Lazarus we have CORBA interfaces, and I made no secret that I like CORBA interfaces much more (basically, they work more like Java and C# interfaces, and are not entangled with unrelated things like memory management or COM technology). But Delphi only has COM interfaces, so CORBA interfaces are not available to us.

      This introduces quirky code when using interfaces, as we do not want the automatic garbage collection that the COM interfaces bring (and one has to watch out for it, even with hacked _AddRef, _Release like TComponent does). So one has to watch for lifetime of temporary values.

  3. CoordinateInterpolator in sprite sheets can be often much simpler or even removed completely. This saves memory and execution time.

Start the discussion at Castle Game Engine Forum