2021 March 11 - 17:31 Debug vs release builds

I was using a “lazy” property (similar to Wheel1) in the hot path for a project, and when running on [POPULAR GAMING CONSOLE] the game was spending over a millisecond on just the null check according to the profiler. So decided to test how expensive the Unity null check really is.

TLDR: it’s not really a problem on release builds, using the Unity profiler for profiling scripts can be really misleading.

The properties tested:

WheelCollider Wheel0 => wheelPreCached;

WheelCollider Wheel1
{
    get
    {
        if (wheelLazyCached == null)
            wheelLazyCached = GetComponent<WheelCollider>();
        return wheelLazyCached;
    }
}

WheelCollider Wheel2 => GetComponent<WheelCollider>();

WheelCollider Wheel3
{
    get
    {
        TryGetComponent(out WheelCollider wheel3);
        return wheel3;
    }
}

The test results (10,000 iterations, times in milliseconds):

- Mac Editor

Wheel0: 0.1976
Wheel1: 0.5487
Wheel2: 0.6233
Wheel3: 1.3072

- [Popular console] Debug build (15-30x slower than the editor!! (very different hardware however) )

Wheel0: 3.1968
Wheel1: 16.0642 (null check is almost as slow as running GetComponent every time!)
Wheel2: 18.3008
Wheel3: 21.2258

- [Popular console] Release with "Explicit Null Checks"

Wheel0: 0.0015
Wheel1: 0.3846 (cost of null check is now tiny)
Wheel2: 4.2519
Wheel3: 5.1337

- [Popular console] Release without "Explicit Null Checks"

Wheel0: 0.0008
Wheel1: 0.3860
Wheel2: 4.9095
Wheel3: 6.1096

- Windows Release

Wheel0: 0.0030
Wheel1: 0.0692
Wheel2: 0.6131
Wheel3: 0.8053