Possible bug with Null coalesce (?? operator)

I was running a speed test of the ?? operator vs if statement just out of curiosity. Here’s my code:

public class test : MonoBehaviour {
	
	
	Transform poo2;
	
	
	// Use this for initialization
	void Start () {
		poo2 = null;
	}
	
	// Update is called once per frame
	void Update () 
	{
		
		//timey = Time.deltaTime;
		
		Transform poo = null;
		
		float time1 = Time.realtimeSinceStartup;
		
		for (int i = 0; i < 4000000; i++)
		{
			if (poo2 == null)
			{
				poo = transform; 
			}
			
			
		}
		
		
		float time2 = Time.realtimeSinceStartup;
		
		for (int i = 0; i < 4000000; i++)
		{	
			poo = poo2 ?? transform;
			
			
		}
		
		float time3 = Time.realtimeSinceStartup;
		
		Debug.Log ("Time 1: " + (time2 - time1));
		Debug.Log ("Time 2: " + (time3 - time2));
	
	}
	
	
}

Excuse my variable names, poo is my go to for test variables, don’t know why. Anyway, I seem to get two sets of results.

So basically:

  1. Enter play mode with script enabled
    Results: “Time 1: 0.25”, “Time 2: 0.15”

  2. Edit script, add a space just so when I go back to Unity, it recompiles
    Results: “Time 1: 0.3”, “Time 2: 0.01”

This seems quite strange, not sure what it is causing it, is there a logical explanation? Or is it a bug?

I just ran a slightly modified version of your code in a standard MS.Net console application. This is my code:

    Stopwatch sw = new Stopwatch();

    for (int k = 0; k < 10; k++)
    {
        object test = null;
        object test2;
        object test3 = new object();

        sw.Start();

        for (int i = 0; i < 40000000; i++)
        {
            if (test == null)
            {
                test2 = test3;
            }
        }

        sw.Stop();
        Console.Out.WriteLine("Checking for null myself: " + 1000d * sw.ElapsedTicks / Stopwatch.Frequency);
        sw.Reset();
        sw.Start();

        for (int i = 0; i < 40000000; i++)
        {
            test2 = test ?? test3;
        }

        sw.Stop();
        Console.Out.WriteLine("Null coalescing: " + 1000d * sw.ElapsedTicks / Stopwatch.Frequency);
        sw.Reset();
    }

Notice that I changed the loops to run 40.000.000 times instead of ‘only’ 4.000.000 times. In addition, I wrapped everything inside an outer loop that repeats the test 10 times.

The results in the console look like this (exact copy paste):

Checking for null myself: 89,2050381982166
Null coalescing: 89,8591575654927
Checking for null myself: 90,4329835540445
Null coalescing: 89,1238392550706
Checking for null myself: 88,9816656408634
Null coalescing: 89,849196356854
Checking for null myself: 89,6228052514284
Null coalescing: 89,1513080425289
Checking for null myself: 88,8920147631149
Null coalescing: 89,1274615127574
Checking for null myself: 90,1320343112322
Null coalescing: 89,6819687936463
Checking for null myself: 89,9669197316752
Null coalescing: 89,9711456989765
Checking for null myself: 88,8234937218728
Null coalescing: 88,8014583209447
Checking for null myself: 88,8515662189456
Null coalescing: 89,4613129295583
Checking for null myself: 88,8192677545715
Null coalescing: 89,8368203097574
Press any key to continue . . .

The numbers are ms.

Conclusion:

There is virtually no difference.