Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the conditional (ternary) operator seem significantly faster?

Tags:

c#

stopwatch

EDIT

If I use Stopwatch correctly and up the number of iterations by two orders of magnitude I get

Ternary took 22404ms

Normal took 21403ms

These results are closer to what I was expecting and make me feel all is right with the world (if not with my code.)

The Ternary/Conditional operator is in fact marginally slower.


Following on from this question, which I have partially answered.

I compile this console app in x64 Release Mode, with optimizations on, and run it from the command line without a debugger attached.

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 don't get any exceptions and the output to the console is somthing close to,

Ternary took 107ms

Normal took 230ms

When I break down the CIL for the 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
}

Whilst the Ternary CIL is a little shorter, it seems to me that the execution path through the CIL for either function takes 3 loads and 1 or 2 jumps and a return. Why does the Ternary function appear to be twice as fast.

I underdtand that, in practice, they are both very quick and indeed, quich enough but, I would like to understand the discrepancy.

like image 307
Jodrell Avatar asked Sep 17 '12 15:09

Jodrell


People also ask

Is conditional operator faster or slower in run time than if statement in C?

It is not faster. There is one difference when you can initialize a constant variable depending on some expression: const int x = (a<b) ?

Is ternary operator fast?

Yes! The second is vastly more readable.

Why ternary operator is better than if-else?

There's a different emphasis: An if / else statement emphasises the branching first and what's to be done is secondary, while a ternary operator emphasises what's to be done over the selection of the values to do it with.

Is ternary operator faster than switch?

There should not be a major difference in speed. However, the switch is far more readable and maintainable. The switch option is easier to debug.


1 Answers

The two take pretty much exactly the same amount of time.

Your results are off because you simply didn’t use Stopwatch correctly. The measurement for “Normal” includes the time taken by both loopers.

If you change the second

stopwatch.Start();

to

stopwatch.Restart();

Then you will get the correct results.


By the way, to get a fairer comparison, you should probably execute

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

instead of

    return value + (condition ? 2 : 1);

so that it is exactly equivalent to the other function. Otherwise you’re measuring not only the conditional operator.

like image 153
Timwi Avatar answered Sep 19 '22 00:09

Timwi