Teljesítmény a .NET Core-ban

Teljesítmény a .NET Core-ban

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 a hivatkozást egy jó cikkre, ahol részletesen összehasonlítják.

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:

Teljesítmény a .NET Core-ban

Teljesítmény a .NET Core-ban

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: https://habr.com/ru/post/124910/. 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):

Teljesítmény a .NET Core-ban

Teljesítmény a .NET Core-ban

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:

Teljesítmény a .NET Core-ban

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();
        }

Teljesítmény a .NET Core-ban

Teljesítmény a .NET Core-ban

.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.

Teljesítmény a .NET Core-ban

Teljesítmény a .NET Core-ban

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: https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/

Teljesítmény a .NET Core-ban

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.

Link a githubra

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster