Ternary operator is twice as slow as an if-else block?

后端 未结 10 942
无人及你
无人及你 2020-11-30 16:20

I read everywhere that ternary operator is supposed to be faster than, or at least the same as, its equivalent if-else block.

However, I di

10条回答
  •  离开以前
    2020-11-30 16:39

    EDIT: All change... see below.

    I can't reproduce your results on the x64 CLR, but I can on x86. On x64 I can see a small difference (less than 10%) between the conditional operator and the if/else, but it's much smaller than you're seeing.

    I've made the following potential changes:

    • Run in a console app
    • Build with /o+ /debug-, and run outside the debugger
    • Run both pieces of code once to JIT them, then lots of times for more accuracy
    • Use Stopwatch

    Results with /platform:x64 (without the "ignore" lines):

    if/else with 1 iterations: 17ms
    conditional with 1 iterations: 19ms
    if/else with 1000 iterations: 17875ms
    conditional with 1000 iterations: 19089ms
    

    Results with /platform:x86 (without the "ignore" lines):

    if/else with 1 iterations: 18ms
    conditional with 1 iterations: 49ms
    if/else with 1000 iterations: 17901ms
    conditional with 1000 iterations: 47710ms
    

    My system details:

    • x64 i7-2720QM CPU @2.20GHz
    • 64-bit Windows 8
    • .NET 4.5

    So unlike before, I think you are seeing a real difference - and it's all to do with the x86 JIT. I wouldn't like to say exactly what is causing the difference - I may update the post later on with more details if I can bother to go into cordbg :)

    Interestingly, without sorting the array first, I end up with tests which take about 4.5x as long, at least on x64. My guess is that this is to do with branch prediction.

    Code:

    using System;
    using System.Diagnostics;
    
    class Test
    {
        static void Main()
        {
            Random r = new Random(0);
            int[] array = new int[20000000];
            for(int i = 0; i < array.Length; i++)
            {
                array[i] = r.Next(int.MinValue, int.MaxValue);
            }
            Array.Sort(array);
            // JIT everything...
            RunIfElse(array, 1);
            RunConditional(array, 1);
            // Now really time it
            RunIfElse(array, 1000);
            RunConditional(array, 1000);
        }
    
        static void RunIfElse(int[] array, int iterations)
        {        
            long value = 0;
            Stopwatch sw = Stopwatch.StartNew();
    
            for (int x = 0; x < iterations; x++)
            {
                foreach (int i in array)
                {
                    if (i > 0)
                    {
                        value += 2;
                    }
                    else
                    {
                        value += 3;
                    }
                }
            }
            sw.Stop();
            Console.WriteLine("if/else with {0} iterations: {1}ms",
                              iterations,
                              sw.ElapsedMilliseconds);
            // Just to avoid optimizing everything away
            Console.WriteLine("Value (ignore): {0}", value);
        }
    
        static void RunConditional(int[] array, int iterations)
        {        
            long value = 0;
            Stopwatch sw = Stopwatch.StartNew();
    
            for (int x = 0; x < iterations; x++)
            {
                foreach (int i in array)
                {
                    value += i > 0 ? 2 : 3;
                }
            }
            sw.Stop();
            Console.WriteLine("conditional with {0} iterations: {1}ms",
                              iterations,
                              sw.ElapsedMilliseconds);
            // Just to avoid optimizing everything away
            Console.WriteLine("Value (ignore): {0}", value);
        }
    }
    

提交回复
热议问题