Porównaj wydajność .NET Framework vs .NET Core vs .NET 5

Microsoft obecnie skupił się już na najnowszym runtime .NET Core i NET 5. Jednakże zapewne wielu deweloperów nadal działa na starym .NET Frameworku. Czy warto migrować/przesiadać się na .NET Core? Od strony wydajnościowej - TAK i to jak najszybciej!

O mitycznym przyspieszeniu w runtime .NET Core w porównaniu do .NET Framework pisano już wiele. Oczywiście suche wynik zapewne powiedzą więcej niż tysiące słów i zachwytów. Każdy zainteresowany może wejść na GitHuba:
https://github.com/djfoxer/DotNetFrameworkVsCore
gdzie stworzyłem jeden wspólny test, który odpalany jest na .NET Core i .NET Framewrok. Kod jest otwarty i oparty na wpisach blogowych Microsoftu na temat wydajności w runtime.

using BenchmarkDotNet.Attributes;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;

namespace djfoxer.DotNetFrameworkVsCore.Common
{
    public class MainBenchmark
    {
        IEnumerable<int> _tenMillionToZero = Enumerable.Range(0, 10_000_000).Reverse();
        byte[] _raw = new byte[100 * 1024 * 1024];
        SHA256 _sha = SHA256.Create();
        static string _s = "abcdefghijklmnopqrstuvwxyz";

        [GlobalSetup]
        public void BenchmarkSetup()
        {
            for (int index = 0; index < _raw.Length; index++) _raw[index] = (byte)index;
        }

        [Benchmark]
        public DayOfWeek EnumParse() => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), "Thursday");

        [Benchmark]
        public int LinqOrderBySkipFirst()
        {
           return _tenMillionToZero.OrderBy(i => i).Skip(4).First();
        }

        [Benchmark]
        public byte[] Sha256()
        {
            return _sha.ComputeHash(_raw);
        }

        [Benchmark]
        public bool StringStartsWith()
        {
            var data = false;
            for (int i = 0; i < 100_000_000; i++)
            {
                data = _s.StartsWith("abcdefghijklmnopqrstuvwxy-", StringComparison.Ordinal);
            }
            return data;
        }

        [Benchmark]
        public object Deserialize()
        {
            var books = new List<BookToSerialize>();
            for (int i = 0; i < 1_00000; i++)
            {
                string id = i.ToString();
                books.Add(new BookToSerialize { Name = id, Id = id });
            }

            var formatter = new BinaryFormatter();
            var mem = new MemoryStream();
            formatter.Serialize(mem, books);
            mem.Position = 0;

            return formatter.Deserialize(mem);
        }
    }
}

.NET Framework vs .NET Core

Na GitHubie znajdziecie wyniki testów przeprowadzone na procesorach AMD i Intel. I tu ciekawostka. .NET Core wykorzystuje w pełni możliwość kryptograficzne procesorów AMD, co pozwala na 14x przyspieszenie w obliczaniu testowego SHA256! Wszystko dzięki użyciu natywnych(!) bibliotek kryptograficznych - CNG na Windows, a OpenSSL na Unixie.

Większość testów działa od 2x do 14x szybciej na .NET Core, niż dokładnie ten sam kod odpalony na runtime .NET Framework. 

Enum 2x - poprawki w Enum.Parse/TryParse

Linq 8x - optymalizacje Linq, przepisane operatory

SHA256 2x-14x - użycie natywnej kryptografii w C++ (.NET Framework nie wykorzystuje ficzerów w procesorach AMD!), CNG na Windows / OpenSSL na Unix. O tym dlaczego AMD w kryptografii jest szybsze niż Intel znajdziecie tutaj: Will AMD’s Ryzen finally bring SHA extensions to Intel’s CPUs?

String 2x-3x - poprawki wydajnościowe związane ze operacjami na stringach

Deserialize 2x-12x - szybsza deserializacja na dużych obiektach

.NET 5

Na dniach MS wydał .NET 5 preview 1. Kod na GitHubie został już uzupełniony o nowy runtime. W celu przetestowania go należy pobrać testowe wydania: Visual Studio 2019 16.6.0 preview oraz .NET 5.0 Preview 1 SDK.

Z pierwszych testów wynika, iż różnicy (wydajnościowej) pomiędzy runtime Core, a .NET 5 nie ma. Tutaj jednak Microsoft zaznaczył, iż skupił się na przyspieszeniu wydajności w wyrażeniach regularnych i niedługo ma pojawić się szczegółowy post na ten temat. Zapewne po jego publikacji kod i wykresy, jak i ten wpis, zostaną zaktualizowane. 

Zapraszam do zaktualizowanej wersji wpisu:
.NET Framework (4.8) vs .NET Core (3.1.x) vs .NET 5

Umarł .NET Framework, niech żyje .NET Core (oraz .NET 5) i jego wydajn...