.NET Core'i tulemuslikkus

.NET Core'i tulemuslikkus

.NET Core'i tulemuslikkus

Tere kõigile! See artikkel on parimate praktikate kogumik, mida mina ja mu kolleegid oleme juba pikka aega rakendanud erinevates projektides.

Teave masina kohta, millel arvutused toimusid:BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-8250U CPU 1.60GHz (Kaby Lake R), 1 CPU, 8 loogilist ja 4 füüsilist tuuma
.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

Töö=Core Runtime=Core

ToList vs ToArray ja tsüklid


Seda teavet plaanisin koostada koos .NET Core 3.0 väljaandmisega, kuid mind eelnesid, ma ei taha varastada teiste kuulsust ega kopeerida kellegi teise teavet, seega lihtsalt viitan hea artikli lingile, kus võrreldakse üksikasjalikult.

Esmalt tahan teile esitada oma mõõtmised ja tulemused, olen lisanud neisse vastupidiseid tsükleid neile, kes eelistavad “C++ stiilis” tsükkel kirjutamist.

Kood:

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 ja 3.0 töökiirus on peaaegu identne. Siin on, mida suutsin .NET Core 3.0 puhul saavutada:

.NET Core'i tulemuslikkus

.NET Core'i tulemuslikkus

Võime järeldada, et massiivide tüüpi kollektsiooni tsükliline töötlemine on kiirem, tänu selle sisemistele optimeerimistele ja selgele kollektsiooni suuruse määramisele. Tuleb meeles pidada, et List tüüpi kollektsioonil on oma eelised ja peaksite kasutama sobivat kollektsiooni sõltuvalt vajalikest arvutustest. Isegi kui loote tsüklite töötlemise loogika, ärge unustage, et see on tavaline tsükkel ja see on samuti võimalik tsüklite optimeerimisele. https://habr.com/ru/post/124910/Habr'is ilmus sellest juba mõnda aega tagasi artikkel:

Throw

Aasta tagasi töötasin ettevõttes legacy projektiga, kus olema pidanud valdkondade valideerimist käsitlema try-catch-throw konstruktsiooniga. Juba siis mõistsin, et see ei ole projekti jaoks tervislik äriotsustus, seetõttu püüdsin võimalusel sellist konstruktsiooni mitte kasutada. Aga vaatame, miks on vale lähenemine vigu sellise konstruktsiooniga käsitleda. Kirjutasin väikese koodi, et võrrelda kahte lähenemist ja sain igas variandis 'benchi' tulemused.

Kood:

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

.NET Core 3.0 ja Core 2.2 tulemused on sarnased (.NET Core 3.0):

.NET Core'i tulemuslikkus

.NET Core'i tulemuslikkus

Try catch muudab koodi mõistmise keerulisemaks ja suurendab teie programmi täitmise aega. Kuid kui see konstruktsioon on vajalik, ei tohiks lisada neid koodireale, millelt ei oodata veakäsitlust – see lihtsustab koodi arusaamist. Tegelikult koormab süsteemi mitte niivõrd erandite töötlemine, vaid vigade väljapanek konstruktsiooni throw new Exception kaudu.

Vigade väljapanek töötab aeglasemalt kui mõni klass, mis kogub vea soovitud formaati. Kui töötate vormi või mõne andmega ja teate selgelt, milline viga peaks olema, siis miks mitte neid käsitleda?

Ei tohi kirjutada konstruktsiooni throw new Exception(), kui see olukord ei ole erandlik. Erandi töötlemine ja väljapanek on väga kulukas!!!

ToLower, ToLowerInvariant, ToUpper, ToUpperInvariant

Oma viie aasta kogemuse jooksul .NET platvormil olen kohanud mitmeid projekte, mis kasutasid stringide võrdlemist. Samuti olen näinud järgmist pilti: oli üks Enterprise lahendus mitme projektiga, millest igaühes tehti stringide võrdlemist erinevalt. Kuid mida tuleks kasutada ja kuidas seda ühtlustada? Raamatust CLR via C# Rihteri kirjutatud ma lugesin, et meetod ToUpperInvariant() töötab kiiremini kui ToLowerInvariant().

Raamatust väljavõte:

.NET Core'i tulemuslikkus

Muidugi ma ei uskunud seda ja otsustasin teha mõned testid siis veel .NET Frameworkil ning tulemused šokeerisid mind — üle 15% jõudluse kasvu. Järgmisel hommikul, kui tööle läksin, näitasin need mõõtmised oma ülemusele ja andsin neile ligipääsu lähtekoodidele. Pärast seda muudeti 2 14-st projektist uute mõõtmiste jaoks, ja arvestades, et need kaks projekti olid loodud tohutute Exceli tabelite töötlemiseks, oli tulemus toote jaoks märkimisväärne.

Samuti esitan teile mõõtmised erinevate .NET Core versioonide jaoks, et igaühel oleks võimalus valida kõige optimaalsem lahendus. Ja tahan lisada, et ettevõttes, kus ma töötan, kasutame ToUpper() stringide võrdlemiseks.

Kood:

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'i tulemuslikkus

.NET Core'i tulemuslikkus

.NET Core 3.0-s on igaühe jaoks neist meetoditest kasv ~x2 ja tasakaalustab teostusi omavahel.

.NET Core'i tulemuslikkus

.NET Core'i tulemuslikkus

Tier Compilation

Oma eelnevas artiklis kirjeldasin seda funktsionaalsust lühidalt ja soovin oma sõnu täiendada. Aste-astmelise kompileerimise kasutamine kiirendab teie lahenduse käivitusaega, kuid peate arvestama, et teie koodi osad kompileeritakse taustal optimeeritud versiooniks, mis võib tuua kaasa väikese ülekoormuse. .NET Core 3.0 tulekuga on projektide ehitusaeg, kui on sisse lülitatud tier compilation, vähenenud ning selle tehnoloogiaga seotud vead on parandatud. Varem põhjustas see tehnoloogia ASP.NET Core'i esimesi päringuvigu ning hangumist esimesel kompileerimisel astmelise kompileerimise režiimis. Hetkel on .NET Core 3.0-s see vaikimisi sisse lülitatud, kuid soovikorral saate selle välja lülitada. Kui olete team-lead, senior, middle või osakonna juht, peaksite mõistma, et projekti kiire arendamine suurendab meeskonna väärtust ja see tehnoloogia võimaldab teil säästa nii arendajate aega kui ka projekti tööaega.

.NET taseme tõstmine

Tõstke oma .NET Frameworki / .NET Core'i versioon. Sageli annab iga uus versioon täiendava jõudluse kasvu ja lisab uusi funktsioone.

Aga millised on täpselt eelised? Vaatame mõningaid neist:

  • .NET Core 3.0-s on täiustatud R2R pildid, mis vähendavad .NET Core rakenduste käivitusaega.
  • Alates versioonist 2.2 on lisatud Tier Compilation, mille abil saavad arendajad projekti käivitamiseks vähem aega kasutada.
  • Uute .NET Standardi standardite toetus.
  • Uue programmeerimiskeele versiooni toetus.
  • Optimeerimine; iga uue versiooniga paranevad `Collection`/`Struct`/`Stream`/`String`/`Regex` põhiraamatukogude optimeerimise omadused ja palju muud. Kui liigute .NET Frameworkilt .NET Core'ile, saavutate kohe suurepärase jõudluse kasvu. Näiteks jagan linki osale optimeerimistest, mis on lisatud .NET Core 3.0-s: https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/

.NET Core'i tulemuslikkus

Kokkuvõte

Koodi kirjutamisel on oluline pöörata tähelepanu erinevatele projektiaspektidele ning kasutada oma programmeerimiskeele ja platvormi funktsioone parima tulemuse saavutamiseks. Olen tänulik, kui jagate oma teadmisi, mis on seotud .NET optimeerimisega.

Link githubile

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster