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...
Komentarze
Prześlij komentarz