Jõudlus .NET Core'is

Jõudlus .NET Core'is

Jõudlus .NET Core'is

Tere kõigile! See artikkel on parimate tavade kogumik, mida mu kolleegid ja mina oleme erinevate projektide kallal töötades pikka aega kasutanud.

Teave masina kohta, millel arvutused tehti:BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-8250U protsessor 1.60 GHz (Kaby Lake R), 1 protsessor, 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), 64-bitine RyuJIT
Tuum: .NET Core 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), 64-bitine RyuJIT
[Host]: .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64-bitine RyuJIT
Tuum: .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64-bitine RyuJIT

Töö=Tuum Runtime=Tuum

ToList vs ToArray ja tsüklid


Plaanisin selle teabe ette valmistada .NET Core 3.0 väljalaskmisega, kuid nad peksid mind sellega, ma ei taha kellegi teise au varastada ja teiste inimeste teavet kopeerida, nii et juhin lihtsalt tähelepanu link heale artiklile, kus võrdlust on üksikasjalikult kirjeldatud.

Enda nimel tahan teile lihtsalt tutvustada oma mõõtmisi ja tulemusi; lisasin neile pöördsilmused, mis on mõeldud kirjutamissilmuste “C++ stiili” austajatele.

kood:

public class Bench
    {
        private List<int> _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 < _list.Count; i++)
            {
                total += _list[i];
            }

            return total;
        }
        
        [Benchmark]
        public int ForListFromEnd()
        {
            int total = 0;t
            for (int i = _list.Count-1; 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 < _array.Length; i++)
            {
                total += _array[i];
            }

            return total;
        }
        
        [Benchmark]
        public int ForArrayFromEnd()
        {
            int total = 0;
            for (int i = _array.Length-1; i > 0; i--)
            {
                total += _array[i];
            }

            return total;
        }
    }

NET Core 2.2 ja 3.0 jõudluskiirused on peaaegu identsed. NET Core 3.0-s õnnestus mul saada järgmist.

Jõudlus .NET Core'is

Jõudlus .NET Core'is

Võime järeldada, et massiivikogu iteratiivne töötlemine on selle sisemise optimeerimise ja selgesõnalise kogu suuruse jaotuse tõttu kiirem. Samuti tasub meeles pidada, et loendikogul on oma eelised ja vastavalt vajalikele arvutustele peaksite kasutama õiget kogu. Isegi kui kirjutate silmustega töötamiseks loogikat, ärge unustage, et see on tavaline tsükkel ja see allub ka võimalikule silmuse optimeerimisele. Habril ilmus üsna kaua aega tagasi artikkel: https://habr.com/ru/post/124910/. See on endiselt asjakohane ja soovitatav lugeda.

Viskama

Aasta tagasi töötasin ühes ettevõttes pärandprojekti kallal, selles projektis oli tavaline väljade valideerimist läbi proovi-püüa-viska konstruktsiooni. Sain juba siis aru, et see on projekti jaoks ebatervislik äriloogika, nii et kui vähegi võimalik, püüdsin sellist kujundust mitte kasutada. Kuid mõelgem välja, miks on sellise konstruktsiooniga vigade käsitlemine halb. Kirjutasin kahe lähenemisviisi võrdlemiseks väikese koodi ja koostasin iga võimaluse jaoks võrdlusalused.

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

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

Jõudlus .NET Core'is

Jõudlus .NET Core'is

Proovi püüdmine muudab koodi raskemini mõistetavaks ja pikendab teie programmi täitmisaega. Kuid kui teil on seda konstruktsiooni vaja, ärge sisestage neid koodiridu, millelt ei eeldata vigu - see muudab koodi arusaadavamaks. Tegelikult ei laadi süsteemi mitte niivõrd erandite käsitlemine, vaid pigem vigade endi loopimine läbi viska uue erandi konstruktsiooni.

Erandite loopimine on aeglasem kui mõni klass, mis kogub vea vajalikus vormingus. Kui töötlete vormi või andmeid ja teate selgelt, milles viga peaks olema, siis miks mitte seda töödelda?

Kui see olukord pole erandlik, ei tohiks te kirjutada uut Exception() konstruktsiooni. Erandi käsitlemine ja viskamine on väga kallis!!!

ToLower, ToLowerInvariant, ToUpper, ToUpperInvariant

Oma 5-aastase .NET-platvormil töötamise kogemuse jooksul olen kokku puutunud paljude projektidega, mis kasutasid stringide sobitamist. Nägin ka järgmist pilti: oli üks Enterprise lahendus paljude projektidega, millest igaüks tegi stringide võrdlusi erinevalt. Mida aga kasutada ja kuidas seda ühtlustada? Richteri raamatust CLR via C# lugesin infot, et meetod ToUpperInvariant() on kiirem kui ToLowerInvariant().

Väljavõte raamatust:

Jõudlus .NET Core'is

Muidugi ei uskunud ma seda ja otsustasin .NET Frameworkis mõned testid läbi viia ja tulemus šokeeris mind – jõudluse kasv enam kui 15%. Seejärel näitasin järgmisel hommikul tööle jõudes neid mõõte ülemustele ja andsin neile juurdepääsu lähtekoodile. Pärast seda muudeti 2 projekti 14-st uute mõõtmiste jaoks ja arvestades, et need kaks projekti eksisteerisid tohutute Exceli tabelite töötlemiseks, oli tulemus toote jaoks enam kui oluline.

Esitan teile ka .NET Core'i erinevate versioonide mõõdud, et igaüks saaks teha valiku optimaalseima lahenduse kasuks. Ja ma tahan lihtsalt lisada, et ettevõttes, kus ma töötan, kasutame stringide võrdlemiseks ToUpper().

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

Jõudlus .NET Core'is

Jõudlus .NET Core'is

Versioonis .NET Core 3.0 on iga meetodi kasv ~x2 ja see tasakaalustab juurutused omavahel.

Jõudlus .NET Core'is

Jõudlus .NET Core'is

Taseme koostamine

Oma viimases artiklis kirjeldasin seda funktsiooni lühidalt, tahaksin oma sõnu parandada ja täiendada. Mitmetasandiline kompileerimine kiirendab teie lahenduse käivitusaega, kuid ohverdate selle, et teie koodi osad kompileeritakse taustal optimeeritud versiooniks, mis võib tekitada väikese lisakulu. NET Core 3.0 tulekuga on lubatud tasandi kompileerimisega projektide ehitusaeg vähenenud ja selle tehnoloogiaga seotud vead on parandatud. Varem põhjustas see tehnoloogia tõrkeid ASP.NET Core'i esimestes päringutes ja hangus mitmetasandilises kompileerimisrežiimis esimese järgu ajal. Praegu on see .NET Core 3.0-s vaikimisi lubatud, kuid soovi korral saate selle keelata. Kui olete meeskonna juht, vanem, keskastme või osakonnajuhataja, siis peate mõistma, et kiire projektiarendus tõstab meeskonna väärtust ja see tehnoloogia võimaldab säästa mõlema arendaja aega. ja projekti enda aeg.

.NET tase üles

Uuendage oma .NET Frameworki / .NET Core versiooni. Sageli suurendab iga uus versioon jõudlust ja lisab uusi funktsioone.

Aga mis kasu täpselt on? Vaatame mõnda neist:

  • .NET Core 3.0 tutvustas R2R-kujutisi, mis vähendavad .NET Core'i rakenduste käivitusaega.
  • Versiooniga 2.2 ilmus Tier Compilation, tänu millele kulutavad programmeerijad projekti käivitamisele vähem aega.
  • Uute .NET-standardite tugi.
  • Programmeerimiskeele uue versiooni tugi.
  • Optimeerimine, iga uue versiooniga paraneb põhiteekide kogu/struktuur/voog/string/regex ja palju muud optimeerimine. Kui lähete .NET Frameworkilt üle .NET Core'ile, saate suure jõudluse tõuke. Näitena lisan lingi mõnele .NET Core 3.0-le lisatud optimeerimisele: https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/

Jõudlus .NET Core'is

Järeldus

Koodi kirjutades tasub tähelepanu pöörata oma projekti erinevatele aspektidele ning kasutada parima tulemuse saavutamiseks oma programmeerimiskeele ja platvormi funktsioone. Mul oleks hea meel, kui jagaksite oma teadmisi .NET-i optimeerimisest.

Link githubile

Allikas: www.habr.com

Lisa kommentaar