Teljesítmény a .NET Core-ban

Helló mindenkinek! Ez a cikk a legjobb gyakorlatok gyűjteménye, amelyeket én és kollégáim hosszú ideje alkalmazunk különböző projekteken.
Információ a gépről, amelyen a számításokat végezték:BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-8250U CPU 1.60GHz (Kaby Lake R), 1 CPU, 8 logikai és 4 fizikai mag
.NET Core SDK=3.0.100
[Host]: .NET Core 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), 64bit RyuJIT
Core: .NET Core 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), 64bit RyuJIT
[Host]: .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT
Core: .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT
Job=Core Runtime=Core
ToList vs ToArray és ciklusok
Ezt az információt a .NET Core 3.0 megjelenésével szerettem volna közzétenni, de megelőztek, nem szeretném ellopni mások dicsőségét és mások munkáját másolni, ezért egyszerűen csak megadom .
Csak annyit szeretnék bemutatni az én méréseim és eredményeim, hogy visszafordított ciklusokat adtam hozzá azoknak, akik kedvelik a "C++ stílusú" ciklusírást.
Kód:
public class Bench
{
private List _list;
private int[] _array;
[Params(100000, 10000000)] public int N;
[GlobalSetup]
public void Setup()
{
const int MIN = 1;
const int MAX = 10;
Random random = new Random();
_list = Enumerable.Repeat(0, N).Select(i => random.Next(MIN, MAX)).ToList();
_array = _list.ToArray();
}
[Benchmark]
public int ForList()
{
int total = 0;
for (int i = 0; i 0; i--)
{
total += _list[i];
}
return total;
}
[Benchmark]
public int ForeachList()
{
int total = 0;
foreach (int i in _list)
{
total += i;
}
return total;
}
[Benchmark]
public int ForeachArray()
{
int total = 0;
foreach (int i in _array)
{
total += i;
}
return total;
}
[Benchmark]
public int ForArray()
{
int total = 0;
for (int i = 0; i 0; i--)
{
total += _array[i];
}
return total;
}
}
.NET Core 2.2 és 3.0 sebessége szinte azonos. Íme, amit a .NET Core 3.0-ban sikerült elérnem:


Arrajtípusú gyűjtemény ciklikus feldolgozása gyorsabb, köszönhetően a belső optimalizálásoknak és a gyűjtemény méretének világos megadásának. Fontos megjegyezni, hogy a List típusú gyűjteményeknek is vannak előnyeik, így mindig a szükséges számítások függvényében válassza a megfelelő gyűjteményt. Még ha ciklusokkal dolgozik is, ne feledje, hogy ez egy szokványos ciklus, amely szintén optimalizálható. A habrán már régóta megjelent egy cikk: . Ez még mindig aktuális és ajánlott elolvasni.
Dobás
Tavaly egy cégnél dolgoztam egy örökölt projekten, ahol a mezők validálását normális keretek között a try-catch-throw struktúrával kellett végezni. Már akkor is éreztem, hogy ez egy egészségtelen üzleti logika, ezért lehetőség szerint próbáltam elkerülni ezt a struktúrát. De nézzük meg, mivel is indokolt ez a megközelítés. Írtam egy kis kódot, hogy összehasonlítsam a két megközelítést, és előkészítettem „bencseket” mindkét változatra.
Kód:
public bool ContainsHash()
{
bool result = false;
foreach (var file in _files)
{
var extension = Path.GetExtension(file);
if (_hash.Contains(extension))
result = true;
}
return result;
}
public bool ContainsHashTryCatch()
{
bool result = false;
try
{
foreach (var file in _files)
{
var extension = Path.GetExtension(file);
if (_hash.Contains(extension))
result = true;
}
if(!result)
throw new Exception("false");
}
catch (Exception e)
{
result = false;
}
return result;
}A .NET Core 3.0 és a Core 2.2 eredményei hasonlóak (.NET Core 3.0):


A try-catch megnehezíti a kód megértését és növeli a program futási idejét. De ha szüksége van erre a struktúrára, ne illessze be azokat a kódsorokat, ahol nem várható hiba kezelés — ez megkönnyíti a kód megértését. Valójában nem a kivételek kezelése terheli a rendszert, hanem maguknak a hibáknak a kiváltása a throw new Exception struktúrával.
A kivételek dobása lassabb bármilyen osztálynál, amely a hibákat a szükséges formátumban gyűjti össze. Ha űrlapot vagy adatokat dolgoz fel, és pontosan tudja, milyen hiba léphet fel, miért ne kezelné azokat?
Nem érdemes az új Exception() szerkezetet használni, ha ez a helyzet nem kivételes. A kivételek kezelése és kidobása nagyon drága!!!
ToLower, ToLowerInvariant, ToUpper, ToUpperInvariant
Öt éves .NET platformon szerzett tapasztalatom során számos projektet láttam, amelyek karaktersorok összehasonlítását használták. Ugyanakkor láttam egy olyan helyzetet is: volt egy vállalati megoldás, sok projekttel, amelyek mindegyike más módon hasonlította össze a karakterláncokat. De mit érdemes használni és hogyan lehet ezt egységesíteni? A CLR via C# könyvben, amit Richter írt, olvastam, hogy a ToUpperInvariant() módszer gyorsabb, mint a ToLowerInvariant().
Kivágás a könyvből:

Természetesen nem hittem el, és teszteket végeztem, még a .NET Framework alatt, és az eredmény sokkolt – több mint 15% teljesítménynövekedés. Amikor másnap reggel munkába értem, megmutattam az adatokat a felettesemnek, és hozzáférést biztosítottam az forráskódokhoz. Ezt követően a 14 projektből 2-t módosítottak az új mérési adatok alapján, és mivel ez a két projekt hatalmas Excel táblázatok feldolgozására irányult, az eredmény a termék szempontjából jelentős volt.
Ezenkívül bemutatom a méréseket a különböző .NET Core verziókhoz, hogy mindenki választhassa a legoptimálisabb megoldást. Csak szeretném kiegészíteni, hogy abban a vállalatban, ahol dolgozom, a ToUpper()-t használjuk a karakterláncok összehasonlítására.
Kód:
public const string defaultString = "VXTDuob5YhummuDq1PPXOHE4PbrRjYfBjcHdFs8UcKSAHOCGievbUItWhU3ovCmRALgdZUG1CB0sQ4iMj8Z1ZfkML2owvfkOKxBCoFUAN4VLd4I8ietmlsS5PtdQEn6zEgy1uCVZXiXuubd0xM5ONVZBqDu6nOVq1GQloEjeRN8jXrj0MVUexB9aIECs7caKGddpuut3";
[Benchmark]
public bool ToLower()
{
return defaultString.ToLower() == defaultString.ToLower();
}
[Benchmark]
public bool ToLowerInvariant()
{
return defaultString.ToLowerInvariant() == defaultString.ToLowerInvariant();
}
[Benchmark]
public bool ToUpper()
{
return defaultString.ToUpper() == defaultString.ToUpper();
}
[Benchmark]
public bool ToUpperInvariant()
{
return defaultString.ToUpperInvariant() == defaultString.ToUpperInvariant();
}


.NET Core 3.0-ban minden egyes módszer teljesítmény-növekedése ~x2, és egyensúlyba hozza a megvalósításokat.


Tier Compilation
Az előző cikkemben röviden bemutattam ezt a funkciót, de szeretném kiegészíteni és pontosítani a szavaimat. A több szintű fordítás felgyorsítja a megoldásod indulási idejét, de azzal kell megküzdened, hogy a kódod egyes részei háttérben optimálisabb verzióra lesznek fordítva, ami kis mértékű költségekkel járhat. A .NET Core 3.0 megjelenésével csökkent a projektek fordítási ideje a tier compilation engedélyezésével, és kijavították az ezzel a technológiával kapcsolatos hibákat. Korábban ez a technológia a kezdeti ASP.NET Core kérések hibáihoz és a több szintű fordítás első fordítása közbeni felfüggesztéséhez vezetett. Jelenleg a .NET Core 3.0-ban alapértelmezetten engedélyezve van, de igény szerint letilthatod. Ha team-lead, szenior, középvezető vagy osztályvezető pozícióban dolgozol, fontos megértened, hogy a projekt gyors fejlesztése növeli a csapat értékét, és ez a technológia segít időt spórolni mind a fejlesztőknek, mind a projekt munkaidejének.
.NET szintemelés
Frissítsd a .NET Framework / .NET Core verziódat. Gyakran minden új verzió további teljesítménynövekedést biztosít és új funkciókat ad hozzá.
De pontosan milyen előnyöket nyújt? Nézzük meg azokat:
- A .NET Core 3.0-ban megjelentek az R2R képek, amelyek lehetővé teszik a .NET Core alkalmazások indítási idejének csökkentését.
- A 2.2-es verzióval megjelent a Tier Compilation, aminek köszönhetően a programozók kevesebb időt fognak költeni a projekt indítására.
- Az új .NET Standard verziók támogatása.
- A programozási nyelv új verziójának támogatása.
- Optimalizáció; minden új verzióval javul a Collection/Struct/Stream/String/Regex és sok egyéb alapkönyvtár optimalizálása. Ha a .NET Framework-ról a .NET Core-ra váltasz, jelentős teljesítménynövekedést kapsz az alapcsomagban. Példaként csatolok egy linket a .NET Core 3.0-ban hozzáadott optimalizációkról:

Zárás
A kód írása során érdemes figyelmet fordítani a projekt különböző aspektusaira és kihasználni a programozási nyelved és platformod funkcióit a legjobb eredmények elérése érdekében. Örömmel várom, ha megosztod velem a .NET optimalizálásával kapcsolatos tudásodat.
Forrás: habr.com
