Performanca në .NET Core

Performanca në .NET Core

Performanca në .NET Core

Përshëndetje të gjithëve! Ky artikull është një grumbull i Praktikave më të Mira që unë dhe kolegët e mi i përdorim për një kohë të gjatë gjatë punës në projekte të ndryshme.

Informacioni mbi makinën ku janë kryer llogaritjet:BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-8250U CPU 1.60GHz (Kaby Lake R), 1 CPU, 8 bërthamë logjike dhe 4 bërthamë fizike
.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

Punë=Core Runtime=Core

ToList vs ToArray dhe Ciklet


Unë planifikova të përgatit këtë informacion me daljen e .NET Core 3.0, por dikush më ka kaluar, nuk dua të vjedh lavdinë e të tjerëve dhe të kopjoj informacionin e tyre, prandaj thjesht do të tregoj një lidhje me një artikull të mirë, ku është përshkruar në detaje krahasimi.

Vetëm dua t'ju paraqes masat dhe rezultatet e mia, kam shtuar në to ciklet e kthimit për ata që pëlqejnë stilin e cikleve “C++”.

Kodi:

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

Shpejtësia e punës në .NET Core 2.2 dhe 3.0 është pothuajse identike. Këto janë ato që arrita të marr në .NET Core 3.0:

Performanca në .NET Core

Performanca në .NET Core

Ne mund të arrijmë në përfundimin se përpunimi ciklik i koleksioneve të tipit Array është më i shpejtë, falë optimizimeve të tij të brendshme dhe përcaktimit të qartë të madhësisë së koleksionit. Gjithashtu, është e rëndësishme të mbani mend se koleksioni i tipit List ka avantazhet e tij dhe duhen përdorur koleksionet e duhura në varësi të llogaritjeve të nevojshme. Edhe pse po shkruani logjikën e punës me ciklet, mos haroni se kjo është një loop e zakonshme dhe gjithashtu i nënshtrohet optimizimeve të mundshme ciklike. Në Habr ka dalë një artikull që e shqyrton këtë temë: https://habr.com/ru/post/124910/. Ai është akoma i vlefshëm dhe rekomandohet për lexim.

Throw

Një vit më parë punoja në një kompani mbi një projekt legacy, dhe në atë projekt ishim në kornizën e duhur për të përpunuar validimin e fushave nëpërmjet konstruktit try-catch-throw. Atyherë e kuptova se kjo ishte një logjikë e sëmurë biznesi për funksionimin e projektit, prandaj sa më shumë që ishte e mundur, përpiqesha të mos përdorja një konstrukt të tillë. Por le të shqyrtojmë se çfarë është e keqe me qasjen e përpunimit të gabimeve nëpërmjet këtij konstrukti. Kam shkruar një kod të vogël për të krahasuar dy qasje dhe kam marrë “benchmark”-et për çdo variant.

Kodi:

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

Rezultatet në .NET Core 3.0 dhe Core 2.2 kanë një rezultat të ngjashëm (.NET Core 3.0):

Performanca në .NET Core

Performanca në .NET Core

Try catch e komplikon kuptimin e kodit dhe rrit kohën e ekzekutimit të programit tuaj. Por nëse keni nevojë për këtë konstrukt, mos e vendosni atë rreshtin e kodit nga i cili nuk pritet të ketë përpunim gabimesh - kjo do ta lehtësojë kuptimin e kodit. Në të vërtetë, ajo që e ngarkon sistemin nuk është aq shumë përpunimi i përjashtimeve, sa hedhja e vetë gabimeve nëpërmjet konstruktit throw new Exception.

Hedhja e përjashtimeve punon më ngadalë se një klasë e cila do të mbledhë gabimin në formatin e duhur. Nëse po përpunoni një formë apo ndonjë të dhënë dhe e dini saktësisht se cila duhet të jetë gabimi, pse mos ta përpunoni atë?

Nuk duheti të shkruash konstrukcionin throw new Exception() nëse kjo situatë nuk është e jashtzakonshme. Trajtimi dhe hedhja e përjashtimeve kushton shumë!!!

ToLower, ToLowerInvariant, ToUpper, ToUpperInvariant

Me përvojën time 5-vjeçare në platformën .NET kam hasur në shumë projekte që përdorin krahasimin e vargjeve. Po ashtu kam parë këtë skenë: kishte një zgjidhje Enterprise me shumë projekte, secili prej të cilëve bëntë krahasimin e vargjeve ndryshe. Por çfarë duhej të përdorej dhe si ta unifikoja atë? Në librin CLR via C# të Rihter-it, kam lexuar informacionin se metoda ToUpperInvariant() punon më shpejt se ToLowerInvariant().

Nxjerrje nga libri:

Performanca në .NET Core

Natyrisht që nuk e besova dhe vendosa të bëj disa teste në atë kohë në .NET Framework dhe rezultati më habiti – mbi 15% rritje të performancës. Më pas, në mëngjesin e ardhshëm, iu tregova të dhënat e matjeve menaxhmentit tim dhe u ofrova atyre akses në kodin burimor. Pas kësaj, 2 nga 14 projektet u modifikuan për matjet e reja, dhe duke marrë parasysh se këto dy projekte ekzistonin për të trajtuar tabela të mëdha excel-i, rezultati ishte shumë domethënës për produktin.

Gjithashtu ju paraqes matjet për versionet e ndryshme të .NET Core, në mënyrë që secili prej jush të mund të bëjë zgjedhjen drejt zgjidhjes më optimale. Dhe dëshiroj të shtoj se në kompaninë ku punoj, ne përdorim ToUpper() për krahasimin e vargjeve.

Kodi:

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

Performanca në .NET Core

Performanca në .NET Core

Në .NET Core 3.0, rritja për secilën nga këto metoda është ~x2 dhe balancohen implementimet mes tyre.

Performanca në .NET Core

Performanca në .NET Core

Tier Compilation

Në artikullin tim të kaluar, përshkruajta shkurtimisht këtë funksionalitet dhe doja të saktësoj dhe të shtoj disa fjalë. Kompilimi në shumënivele shpejton kohën e nisjes së zgjidhjes tuaj, por ju sakrifikoni faktin se pjesë të kodit tuaj do të kompilohet në një version më të optimizuar në sfond, e cila mund të sjellë disa kosto të vogla shtesë. Me ardhjen e NET Core 3.0, kohëzgjatja e ndërtimit të projekteve me kompilimin në tier është reduktuar dhe janë rregulluar defektet e lidhura me këtë teknologji. Më parë, kjo teknologji shkaktonte gabime në kërkesat e para në ASP.NET Core dhe ngadalësim gjatë ndërtimit të parë në mënyrën e kompilimit në shumënivele. Aktualisht, në .NET Core 3.0, ajo është aktivizuar si parazgjedhje, por ju mund ta çaktivizoni nëse dëshironi. Nëse jeni në pozita si team-lead, senior, middle ose drejtor departamenti, duhet të kuptoni se zhvillimi i shpejtë i projektit rrit vlerën e ekipit dhe kjo teknologji do t'ju ndihmojë të kurseni kohë si për zhvilluesit, ashtu edhe për kohën e punës së projektit.

.NET rritje

Rritni versionin tuaj të .NET Framework / .NET Core. Shpesh, çdo version i ri jep një rritje të mëtejshme të performancës dhe shton karakteristika të reja.

Por cilat janë përfitimet specifike? Le të shqyrtojmë disa prej tyre:

  • Në .NET Core 3.0 dolën imazhe R2R, të cilat do të lejojnë të reduktojnë kohën e nisjes së aplikacioneve .NET Core.
  • Që nga versioni 2.2, u prezantua Kompilimi në Tier, që i mundëson programuesve të ndajnë më pak kohë për të nisur projektin.
  • Përkrahja e standardeve të reja të .NET Standard.
  • Përkrahja e versionit të ri të gjuhës së programimit.
  • Optimizimi, me çdo version të ri përmirësohet optimizimi i bibliotekave bazë Collection/Struct/Stream/String/Regex dhe shumë më tepër. Nëse kaloni nga .NET Framework në .NET Core, do të merrni një rritje të madhe të performancës nga kutia. Si shembull, po bashkëngjis një lidhje mbi disa optimizime që u shtuan në .NET Core 3.0: https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/

Performanca në .NET Core

Përfundim

Kur shkruani kod, duhet t'i kushtoni vëmendje aspekteve të ndryshme të projektit tuaj dhe të përdorni funksionet e gjuhës suaj të programimit dhe platformës për të arritur rezultatet më të mira. Do më pëlqente nëse do të ndani njohuritë tuaja lidhur me optimizimin në .NET.

Lidhja në github

Burimi: habr.com

Blini hostim të besueshëm për faqe interneti me mbrojtje DDoS, serverë VPS VDS 🔥 Blini hostim të besueshëm për faqe interneti me mbrojtje DDoS, serverë VPS VDS - ProHoster