Why does a conditional (ternary) operator look much faster?

EDIT

If I use Stopwatchand increase the number of iterations by two orders of magnitude correctly , I get

Ternar took 22404 ms

Normal received 21403 ms

These results are closer to what I expected, and make me feel that everything is right with the world (if not with my code.)

The ternary / conditional operator is actually slightly slower.


Following this question , to which I partially answered.

I compile this console application in x64 release mode with optimization and run it from the command line without an attached debugger.

using System; 
using System.Diagnostics;

class Program
{
    static void Main()
    {
        var stopwatch = new Stopwatch();

        var ternary = Looper(10, Ternary);
        var normal = Looper(10, Normal);

        if (ternary != normal)            {
            throw new Exception();
        }

        stopwatch.Start();
        ternary = Looper(10000000, Ternary);
        stopWatch.Stop();
        Console.WriteLine(
            "Ternary took {0}ms", 
            stopwatch.ElapsedMilliseconds);

        stopwatch.Start();
        normal = Looper(10000000, Normal);
        stopWatch.Stop();
        Console.WriteLine(
            "Normal took {0}ms", 
            stopwatch.ElapsedMilliseconds);

        if (ternary != normal)            {
            throw new Exception();
        }

        Console.ReadKey();
    }

    static int Looper(int iterations, Func<bool, int, int> operation)
    {
        var result = 0;
        for (int i = 0; i < iterations; i++)
        {
            var condition = result % 11 == 4;
            var value = ((i * 11) / 3) % 5;
            result = operation(condition, value);
        }

        return result;
    }

    static int Ternary(bool condition, in value)
    {
        return value + (condition ? 2 : 1);
    }

    static int Normal(int iterations)
    {
        if (condition)
        {
            return = 2 + value;
        }

        return = 1 + value;
    }
}

I get no exceptions and console output is close to

Ternar took 107 ms

Normal accepted 230 ms

When I break CIL into two logical functions, I get this,

... Ternary ...
{
     : ldarg.1      // push second arg
     : ldarg.0      // push first arg
     : brtrue.s T   // if first arg is true jump to T
     : ldc.i4.1     // push int32(1)
     : br.s F       // jump to F
    T: ldc.i4.2     // push int32(2)
    F: add          // add either 1 or 2 to second arg
     : ret          // return result
}

... Normal ...
{
     : ldarg.0      // push first arg
     : brfalse.s F  // if first arg is false jump to F
     : ldc.i4.2     // push int32(2)
     : ldarg.1      // push second arg
     : add          // add second arg to 2
     : ret          // return result
    F: ldc.i4.1     // push int32(1)
     : ldarg.1      // push second arg
     : add          // add second arg to 1
     : ret          // return result
}

Ternary CIL , , CIL 3 1 2 . Ternary .

, , , .

+5
1

.

, Stopwatch . "" , .

stopwatch.Start();

stopwatch.Restart();

.


, , , ,

    return (condition ? value + 2 : value + 1);

    return value + (condition ? 2 : 1);

. .

+8

All Articles