Jamie
Jamie

Reputation: 3051

Why does .NET Core 2.0 perform worse than .NET Framework 4.6.1

I've wrote a program that creates 4 threads which each sort 20.000 numbers from low to high 50 times. I've runned this test several times on .NET Core 2.0 and .NET Framework 4.6.1. In this test .NET Framework always outperforms .NET Core.

Setup

The following code has been used to benchmark the two frameworks.

static void Main()
    {
        const int amountParallel = 4;
        var globalStopwatch = new Stopwatch();

        globalStopwatch.Start();

        var tasks = new Task<double[]>[4];

        for (int i = 0; i < amountParallel; i++)
        {
            tasks[i] = Start();
        }

        Task.WaitAll(tasks);

        globalStopwatch.Stop();

        Console.WriteLine("Averages: {0}ms", tasks.SelectMany(r => r.Result).Average(x => x));
        Console.WriteLine("Time completed: {0}", globalStopwatch.Elapsed.TotalMilliseconds);
    }

    private static Task<double[]> Start()
    {
        return Task.Factory.StartNew(() =>
        {
            var numbersToSort = new int[20000];

            var globalStopwatch = new Stopwatch();
            var individualStopwatch = new Stopwatch();
            var stopwatchTimes = new double[50];
            int temp;

            globalStopwatch.Start();

            for (int i = 0; 50 > i; i++)
            {
                Console.WriteLine("Running task: {0}", i);
                numbersToSort = Enumerable.Range(0, 20000).Reverse().ToArray();
                individualStopwatch.Start();

                for (int indexNumberArray = 0; numbersToSort.Length > indexNumberArray; indexNumberArray++)
                {
                    for (int sort = 0; numbersToSort.Length - 1 > sort; sort++)
                    {
                        if (numbersToSort[sort] > numbersToSort[sort + 1])
                        {
                            temp = numbersToSort[sort + 1];
                            numbersToSort[sort + 1] = numbersToSort[sort];
                            numbersToSort[sort] = temp;
                        }
                    }
                }

                individualStopwatch.Stop();

                Console.WriteLine("Task {0} completed, took: {1}ms", i, Math.Round(individualStopwatch.Elapsed.TotalMilliseconds));

                stopwatchTimes[i] = individualStopwatch.Elapsed.TotalMilliseconds;

                individualStopwatch.Reset();
            }

            globalStopwatch.Stop();

            Console.WriteLine("Total time: {0}s", Math.Round(globalStopwatch.Elapsed.TotalSeconds, 2));
            Console.WriteLine("Average: {0}ms", Math.Round(stopwatchTimes.Average(time => time)));

            return stopwatchTimes;
        }, TaskCreationOptions.LongRunning);
    }

Test results:

.NET Core

.NET Framework

.NET Core isn't slower on only CPU related tasks. It's also slower on disk I/O tasks.

Any idea's why .NET Core is a bit slower on this part? Are there changes I can make to improve the performance of .NET Core?

Upvotes: 14

Views: 4427

Answers (2)

Andy Ayers
Andy Ayers

Reputation: 1112

This should be fixed in .Net Core 2.0.7 and .Net Framework 4.7.2, via https://github.com/dotnet/coreclr/pull/15323

Root cause was a bug in the JIT's Common Subexpression Elimination (aka CSE) optimization. See issue (linked from PR) for gory details.

Upvotes: 10

Jamie
Jamie

Reputation: 3051

.NET Framework projects default to 32-bit code. This option is visible in the build settings of a project and selected by default. .NET Core projects default to 64-bit code. If you untick the "Prefer 32-bit" box you will notice .NET Framework drops in performance.

Another point of note is that the desktop x86 JIT is a separate code base from the x64 JIT. For 64-bit, both .NET Framework and .NET Core use RyuJIT now; for 32-bit .NET Core still uses RyuJIT, but .NET Framework uses the legacy JIT, so you've got both different bitness and a different jitter.

The answers were provided in the comments by Hans Passant and Jeroen Mostert.

Upvotes: 12

Related Questions