.NET framework 4.7.2 to .NET core 3.1 Identical code, 10x SLOWER!

Jean-Claude Morin 1 Reputation point
2021-04-23T21:02:42.343+00:00

Hi, first time posting here, I'm really puzzle.
My company have legacy .NET application and we plan to move to .NET core.
While testing stuff I found the code slow. I did a minimal benchmark and it was 10x slower on my machine. The same identical code, same dev machine. I can repeat both code in any order and get always the same result.

Anyone have any clue why it would be that slower on .NET Core 3.1 vs .NET framework 4.7.2 ?

Both program were compiled with Visual Studio 2019 Community edition. I have been able to reproduce the issue with 2 machines (Windows 10 and Windows 7)

The code involve multi-thread download of files.

public static void Main(string[] args) {
            object lockConsole = new object();
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            Parallel.For(0, 1000, new ParallelOptions { MaxDegreeOfParallelism = 20 },
                i => {
                    try {
                        string url = $"https://www.merehelene.com/i/test-{i}.jpg?size=50";
                        Stopwatch sw = new Stopwatch();
                        sw.Start();

                        using (WebClient client = new WebClient()) {
                            client.DownloadData(url);
                        }
                        lock (lockConsole) {
                            Console.CursorLeft = 0;
                            Console.Write($"{sw.ElapsedMilliseconds}ms");
                        }

                    } catch (Exception e) {
                        Console.WriteLine(e.Message);
                    }
                });
            Console.WriteLine($"Total time: {stopwatch.ElapsedMilliseconds}ms");
            Console.ReadLine();
        }
.NET CLI
.NET CLI
A cross-platform toolchain for developing, building, running, and publishing .NET applications.
322 questions
0 comments No comments
{count} votes

3 answers

Sort by: Most helpful
  1. Daniel Zhang-MSFT 9,611 Reputation points
    2021-04-26T02:06:02.8+00:00

    Hi jcmorin,
    I think it is mostly related to the following reasons.

    1. NET Framework projects default to 32-bit code. This option is visible in the project's build settings and is selected by default. .NET Core projects default to 64-bit code.
    2. 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.
      Best Regards,
      Daniel Zhang

    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

  2. Jcmorin 1 Reputation point
    2021-05-10T12:00:27.597+00:00

    Thanks for the clue, why would I move to a slower version? I should stick with the .NET framework I guess...

    0 comments No comments

  3. Bruce Barker 801 Reputation points
    2021-07-09T16:32:30.793+00:00

    You are using web client incorrectly. Try

    public static void Main(string[] args) {
                object lockConsole = new object();
                WebClient client = new WebClient();
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();
                Parallel.For(0, 1000, new ParallelOptions { MaxDegreeOfParallelism = 20 },
                    i => {
                        try {
                            string url = $"https://www.merehelene.com/i/test-{i}.jpg?size=50";
                            Stopwatch sw = new Stopwatch();
                            sw.Start();
                            client.DownloadData(url);
                            lock (lockConsole) {
                                Console.CursorLeft = 0;
                                Console.Write($"{sw.ElapsedMilliseconds}ms");
                            }
                        } catch (Exception e) {
                            Console.WriteLine(e.Message);
                        }
                    });
                Console.WriteLine($"Total time: {stopwatch.ElapsedMilliseconds}ms");
                Console.ReadLine();
            }
    
    0 comments No comments