Veiktspēja .NET Core

Veiktspēja .NET Core

Veiktspēja .NET Core

Sveiki visiem! Å is raksts ir paraugprakses apkopojums, ko es un mani kolēģi jau ilgu laiku esam izmantojuÅ”i, strādājot pie dažādiem projektiem.

Informācija par maŔīnu, uz kuras tika veikti aprēķini:BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-8250U CPU 1.60 GHz (Kaby Lake R), 1 CPU, 8 loģiskie un 4 fiziskie kodoli
.NET Core SDK=3.0.100
[Saimniekdators]: .NET Core 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), 64 bitu RyuJIT
Kodols: .NET Core 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), 64 bitu RyuJIT
[Saimniekdators]: .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64 bitu RyuJIT
Kodols: .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64 bitu RyuJIT

Darbs=Core Runtime=Core

ToList vs ToArray un cikli


Es plānoju sagatavot Å”o informāciju, izlaižot .NET Core 3.0, bet viņi mani pārspēja, es nevēlos nozagt kāda cita slavu un kopēt citu informāciju, tāpēc es tikai norādÄ«Å”u saite uz labu rakstu, kur ir sÄ«ki aprakstÄ«ts salÄ«dzinājums.

Savā vārdā es tikai vēlos iepazÄ«stināt jÅ«s ar saviem mērÄ«jumiem un rezultātiem; es tiem pievienoju reversās cilpas rakstÄ«Å”anas cilpu ā€œC++ stilaā€ cienÄ«tājiem.

kods:

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 un 3.0 veiktspējas ātrums ir gandrīz identisks. Lūk, ko es varēju iegūt .NET Core 3.0:

Veiktspēja .NET Core

Veiktspēja .NET Core

Varam secināt, ka masÄ«vu kolekcijas iteratÄ«vā apstrāde ir ātrāka, pateicoties tās iekŔējai optimizācijai un skaidrai kolekcijas lieluma pieŔķirÅ”anai. Ir arÄ« vērts atcerēties, ka List kolekcijai ir savas priekÅ”rocÄ«bas, un jums vajadzētu izmantot pareizo kolekciju atkarÄ«bā no nepiecieÅ”amajiem aprēķiniem. Pat ja rakstāt loÄ£iku darbam ar cilpām, neaizmirstiet, ka Ŕī ir parasta cilpa, un tā ir pakļauta arÄ« iespējamai cilpas optimizācijai. Pirms diezgan ilga laika habr tika publicēts raksts: https://habr.com/ru/post/124910/. Tā joprojām ir aktuāla un ieteicama lasāmviela.

Mest

Pirms gada es strādāju uzņēmumā pie mantota projekta, un Å”ajā projektā bija normāli apstrādāt lauka validāciju, izmantojot konstrukciju ā€œmēģini noÄ·ert un mestā€. Jau tad sapratu, ka tā ir neveselÄ«ga biznesa loÄ£ika projektam, tāpēc, kad vien iespējams, centos Ŕādu dizainu neizmantot. Bet izdomāsim, kāpēc pieeja kļūdu novērÅ”anai ar Ŕādu konstrukciju ir slikta. Es uzrakstÄ«ju nelielu kodu, lai salÄ«dzinātu abas pieejas, un katrai opcijai izveidoju etalonus.

kods:

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

Rezultātiem .NET Core 3.0 un Core 2.2 ir līdzīgs rezultāts (.NET Core 3.0):

Veiktspēja .NET Core

Veiktspēja .NET Core

IzmēģināŔanas nozveja padara kodu grÅ«tāk saprotamu un palielina programmas izpildes laiku. Bet, ja jums ir nepiecieÅ”ama Ŕī konstrukcija, nevajadzētu ievietot tās koda rindas, kurās nav paredzēts rÄ«koties ar kļūdām - tas padarÄ«s kodu vieglāk saprotamu. Faktiski sistēmu noslogo ne tik daudz izņēmumu apstrāde, bet gan paÅ”u kļūdu izmeÅ”ana, izmantojot jauno izņēmuma konstrukciju.

Izņēmumu izmeÅ”ana notiek lēnāk nekā dažas klases, kas savāks kļūdu vajadzÄ«gajā formātā. Ja apstrādājat veidlapu vai dažus datus un skaidri zināt, kādai jābÅ«t kļūdai, kāpēc gan to neapstrādāt?

Nevajadzētu rakstÄ«t jaunu Exception() konstrukciju, ja Ŕī situācija nav ārkārtēja. Izņēmuma apstrāde un meÅ”ana ir ļoti dārga!!!

ToLower, ToLowerInvariant, ToUpper, ToUpperInvariant

Savas 5 gadu pieredzes laikā, strādājot pie .NET platformas, esmu saskāries ar daudziem projektiem, kuros tika izmantota virkņu saskaņoÅ”ana. Es redzēju arÄ« Ŕādu attēlu: bija viens Enterprise risinājums ar daudziem projektiem, no kuriem katrs veica virkņu salÄ«dzināŔanu atŔķirÄ«gi. Bet kas bÅ«tu jāizmanto un kā to unificēt? Rihtera grāmatā CLR caur C# es izlasÄ«ju informāciju, ka metode ToUpperInvariant() ir ātrāka par ToLowerInvariant().

Fragments no grāmatas:

Veiktspēja .NET Core

Protams, es tam neticēju un nolēmu veikt dažus testus .NET Framework, un rezultāts mani Å”okēja ā€” veiktspējas pieaugums ir vairāk nekā 15%. Pēc tam, ierodoties darbā nākamajā rÄ«tā, es parādÄ«ju Å”os mērÄ«jumus saviem priekÅ”niekiem un devu viņiem piekļuvi pirmkodam. Pēc tam 2 no 14 projektiem tika mainÄ«ti, lai pielāgotos jaunajiem mērÄ«jumiem, un, ņemot vērā, ka Å”ie divi projekti pastāvēja, lai apstrādātu milzÄ«gas Excel tabulas, rezultāts produktam bija vairāk nekā nozÄ«mÄ«gs.

Piedāvāju arī mērījumus dažādām .NET Core versijām, lai katrs varētu izdarīt izvēli par optimālāko risinājumu. Un es tikai vēlos piebilst, ka uzņēmumā, kurā es strādāju, mēs izmantojam ToUpper(), lai salīdzinātu virknes.

kods:

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

Veiktspēja .NET Core

Veiktspēja .NET Core

Programmā .NET Core 3.0 katras no Ŕīm metodēm pieaugums ir ~x2 un lÄ«dzsvaro implementācijas savā starpā.

Veiktspēja .NET Core

Veiktspēja .NET Core

Līmeņa kompilācija

Savā pēdējā rakstā es Ä«si aprakstÄ«ju Å”o funkcionalitāti, es vēlētos labot un papildināt savus vārdus. Vairāku lÄ«meņu kompilācija paātrina jÅ«su risinājuma palaiÅ”anas laiku, taču jÅ«s upurējat to, ka jÅ«su koda daļas fonā tiks kompilētas optimizētākā versijā, kas var radÄ«t nelielu papildu izdevumu. LÄ«dz ar NET Core 3.0 parādÄ«Å”anos ir samazinājies izveides laiks projektiem ar iespējotu lÄ«meņu kompilāciju, un ir novērstas ar Å”o tehnoloÄ£iju saistÄ«tās kļūdas. IepriekÅ” Ŕī tehnoloÄ£ija izraisÄ«ja kļūdas pirmajos ASP.NET Core pieprasÄ«jumos un sasalst pirmās versijas laikā daudzlÄ«meņu kompilācijas režīmā. PaÅ”laik tas ir iespējots pēc noklusējuma .NET Core 3.0, taču varat to atspējot, ja vēlaties. Ja esi komandas vadÄ«tāja, vecākais, vidējais vai nodaļas vadÄ«tājs, tad jāsaprot, ka strauja projektu attÄ«stÄ«ba palielina komandas vērtÄ«bu un Ŕī tehnoloÄ£ija ļaus ietaupÄ«t laiku abiem izstrādātājiem. un paÅ”a projekta laiks.

.NET līmenis uz augŔu

Jauniniet savu .NET Framework/.NET Core versiju. Bieži vien katra jaunā versija nodroÅ”ina papildu veiktspējas pieaugumu un pievieno jaunas funkcijas.

Bet kādi tieŔi ir ieguvumi? Apskatīsim dažus no tiem:

  • .NET Core 3.0 ieviesa R2R attēlus, kas samazinās .NET Core lietojumprogrammu startÄ“Å”anas laiku.
  • Ar versiju 2.2 parādÄ«jās Tier Compilation, pateicoties kurai programmētāji pavadÄ«s mazāk laika, uzsākot projektu.
  • Atbalsts jauniem .NET standartiem.
  • Atbalsts jaunai programmÄ“Å”anas valodas versijai.
  • Optimizācija, ar katru jauno versiju tiek uzlabota bāzes bibliotēku kolekcija/StruktÅ«ra/Stream/String/Regex optimizācija un daudz kas cits. Ja migrējat no .NET Framework uz .NET Core, jÅ«s iegÅ«sit lielu veiktspējas uzlabojumu. Kā piemēru es pievienoju saiti uz dažām optimizācijām, kas tika pievienotas .NET Core 3.0: https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/

Veiktspēja .NET Core

Secinājums

Rakstot kodu, ir vērts pievērst uzmanÄ«bu dažādiem sava projekta aspektiem un izmantot savas programmÄ“Å”anas valodas un platformas iespējas, lai sasniegtu labāko rezultātu. PriecāŔos, ja padalÄ«tos ar savām zināŔanām par optimizāciju .NET.

Saite uz github

Avots: www.habr.com

Pievieno komentāru