Կատարում .NET Core-ում

Կատարում .NET Core-ում

Կատարում .NET Core-ում

Բարեւ բոլորին! Այս հոդվածը լավագույն փորձի հավաքածու է, որը ես և իմ գործընկերները երկար ժամանակ օգտագործում ենք տարբեր նախագծերի վրա աշխատելիս:

Տեղեկություններ մեքենայի մասին, որի վրա կատարվել են հաշվարկները.BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-8250U պրոցեսոր 1.60 ԳՀց (Kaby Lake R), 1 պրոցեսոր, 8 տրամաբանական և 4 ֆիզիկական միջուկ
.NET Core SDK=3.0.100
[Հոսթ]՝ .NET Core 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), 64 բիթ RyuJIT
Միջուկ՝ .NET Core 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), 64 բիթ RyuJIT
[Հոսթ]՝ .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64 բիթ RyuJIT
Միջուկ՝ .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64 բիթ RyuJIT

Job=Core Runtime=Core

ToList ընդդեմ ToArray-ի և Cycles-ի


Ես նախատեսում էի պատրաստել այս տեղեկատվությունը .NET Core 3.0-ի թողարկմամբ, բայց նրանք ինձ ծեծեցին, ես չեմ ուզում գողանալ ուրիշի փառքը և պատճենել այլ մարդկանց տեղեկատվությունը, այնպես որ ես պարզապես մատնանշեմ. հղում դեպի լավ հոդված, որտեղ համեմատությունը մանրամասն նկարագրված է.

Իմ անունից ես պարզապես ուզում եմ ձեզ ներկայացնել իմ չափումները և արդյունքները, որոնց վրա ես ավելացրել եմ հակադարձ օղակներ գրելու «C++ ոճի» սիրահարների համար:

Կոդ:

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 և 3.0-ի կատարողականի արագությունները գրեթե նույնական են: Ահա թե ինչ կարողացա ստանալ .NET Core 3.0-ում.

Կատարում .NET Core-ում

Կատարում .NET Core-ում

Մենք կարող ենք եզրակացնել, որ Array հավաքածուի կրկնվող մշակումն ավելի արագ է տեղի ունենում՝ շնորհիվ դրա ներքին օպտիմիզացիայի և հավաքածուի չափի հստակ բաշխման: Հարկ է նաև հիշել, որ Ցուցակի հավաքածուն ունի իր առավելությունները, և դուք պետք է օգտագործեք ճիշտ հավաքածուն՝ կախված պահանջվող հաշվարկներից: Նույնիսկ եթե դուք տրամաբանություն եք գրում օղակների հետ աշխատելու համար, մի մոռացեք, որ սա սովորական օղակ է և ենթակա է նաև հնարավոր օղակների օպտիմալացման: Բավականին վաղուց habr-ում հրապարակվել է մի հոդված. https://habr.com/ru/post/124910/. Այն դեռ տեղին է և խորհուրդ է տրվում կարդալ:

Նետում

Մեկ տարի առաջ ես աշխատում էի մի ընկերությունում ժառանգական նախագծի վրա, այդ նախագծում նորմալ էր դաշտի վավերացման գործընթացը փորձել-catch-throw կառուցման միջոցով: Ես այն ժամանակ արդեն հասկացա, որ սա անառողջ բիզնես տրամաբանություն էր նախագծի համար, ուստի հնարավորության դեպքում փորձում էի չօգտագործել նման դիզայն։ Բայց եկեք պարզենք, թե ինչու է սխալների հետ աշխատելու մոտեցումը նման կառուցվածքով վատ: Ես գրեցի մի փոքրիկ ծածկագիր՝ համեմատելու երկու մոտեցումները և յուրաքանչյուր տարբերակի համար նշաձողեր արեցի:

Կոդ:

        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 և Core 2.2-ի արդյունքները ունեն նմանատիպ արդյունք (.NET Core 3.0):

Կատարում .NET Core-ում

Կատարում .NET Core-ում

Փորձեք catch-ը դժվարացնում է ծածկագիրը և մեծացնում ձեր ծրագրի կատարման ժամանակը: Բայց եթե ձեզ անհրաժեշտ է այս կառուցումը, ապա չպետք է տեղադրեք կոդերի այն տողերը, որոնք չեն ակնկալվում, որ կարգավորեն սխալները. դա կդարձնի կոդը ավելի հեշտ հասկանալի: Իրականում, համակարգը բեռնում է ոչ այնքան բացառությունների մշակումը, որքան սխալների նետումը նոր բացառության կառուցվածքի միջոցով:

Բացառություններ նետելը ավելի դանդաղ է, քան որոշ դասեր, որոնք կհավաքեն սխալը պահանջվող ձևաչափով: Եթե ​​դուք մշակում եք ձև կամ որոշ տվյալներ և հստակ գիտեք, թե որն է սխալը, ինչու չմշակել այն:

Դուք չպետք է գրեք նետման նոր Exception() կառուցվածք, եթե այս իրավիճակը բացառիկ չէ: Բացառություն վարելը և գցելը շատ թանկ արժե!!!

ToLower, ToLowerInvariant, ToUpper, ToUpperInvariant

.NET հարթակում աշխատելու իմ 5 տարվա փորձի ընթացքում ես հանդիպել եմ բազմաթիվ նախագծերի, որոնք օգտագործում էին տողերի համապատասխանեցում: Ես տեսա նաև հետևյալ պատկերը. կար մեկ Enterprise լուծում՝ բազմաթիվ նախագծերով, որոնցից յուրաքանչյուրը տարբեր կերպ էր կատարում լարերի համեմատություն։ Բայց ի՞նչ պետք է օգտագործել և ինչպե՞ս միավորել այն։ Ռիխտերի CLR via C# գրքում ես կարդացի տեղեկություն, որ ToUpperInvariant() մեթոդն ավելի արագ է, քան ToLowerInvariant():

Հատված գրքից.

Կատարում .NET Core-ում

Իհարկե, ես չհավատացի դրան և որոշեցի մի քանի թեստեր անցկացնել .NET Framework-ի վրա, և արդյունքը ցնցեց ինձ՝ ավելի քան 15% կատարողականի աճ: Այնուհետև, հաջորդ առավոտ աշխատանքի գալուն պես, ես ցույց տվեցի այս չափումները իմ վերադասներին և թույլ տվեցի նրանց մուտք գործել սկզբնական կոդը: Դրանից հետո 2 նախագծերից 14-ը փոխվեցին նոր չափումներին համապատասխանելու համար, և հաշվի առնելով, որ այս երկու նախագծերը գոյություն ունեին հսկայական Excel աղյուսակներ մշակելու համար, արդյունքն ավելի քան նշանակալի էր արտադրանքի համար:

Ձեզ եմ ներկայացնում նաև .NET Core-ի տարբեր տարբերակների չափումներ, որպեսզի ձեզնից յուրաքանչյուրը կարողանա ընտրություն կատարել դեպի ամենաօպտիմալ լուծումը։ Եվ ես պարզապես ուզում եմ ավելացնել, որ այն ընկերությունում, որտեղ ես աշխատում եմ, մենք օգտագործում ենք ToUpper() տողերը համեմատելու համար:

Կոդ:

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-ում

Կատարում .NET Core-ում

.NET Core 3.0-ում այս մեթոդներից յուրաքանչյուրի աճը կազմում է ~x2 և հավասարակշռում է իրականացումները միմյանց միջև:

Կատարում .NET Core-ում

Կատարում .NET Core-ում

Շերտերի կազմում

Իմ վերջին հոդվածում ես համառոտ նկարագրեցի այս ֆունկցիոնալությունը, ես կցանկանայի ուղղել և լրացնել իմ խոսքերը: Բազմամակարդակ կոմպիլյացիան արագացնում է ձեր լուծման գործարկման ժամանակը, բայց դուք զոհաբերում եք, որ ձեր կոդի մասերը կկազմվեն ավելի օպտիմիզացված տարբերակի հետին պլանում, որը կարող է ներկայացնել փոքր ծախսեր: NET Core 3.0-ի ի հայտ գալուց հետո միացված մակարդակի կոմպիլյացիան ունեցող նախագծերի ստեղծման ժամանակը նվազել է, և այս տեխնոլոգիայի հետ կապված սխալները շտկվել են: Նախկինում այս տեխնոլոգիան հանգեցրեց սխալների ASP.NET Core-ում առաջին հարցումներում և սառեցրեց առաջին կառուցման ընթացքում բազմամակարդակ կոմպիլյացիայի ռեժիմում: Ներկայումս այն լռելյայն միացված է .NET Core 3.0-ում, սակայն ցանկության դեպքում կարող եք անջատել այն: Եթե ​​դուք գտնվում եք թիմի ղեկավարի, ավագ, միջին կամ բաժնի ղեկավարի պաշտոնում, ապա պետք է հասկանաք, որ ծրագրի արագ զարգացումը մեծացնում է թիմի արժեքը, և այս տեխնոլոգիան թույլ կտա ձեզ ժամանակ խնայել երկու մշակողների համար: և բուն նախագծի ժամանակը:

.NET մակարդակի բարձրացում

Թարմացրեք ձեր .NET Framework / .NET Core տարբերակը: Հաճախ յուրաքանչյուր նոր տարբերակ ապահովում է կատարողականի լրացուցիչ ձեռքբերումներ և ավելացնում է նոր հնարավորություններ:

Բայց կոնկրետ որո՞նք են օգուտները: Դիտարկենք դրանցից մի քանիսը.

  • .NET Core 3.0-ը ներկայացրել է R2R պատկերներ, որոնք կնվազեցնեն .NET Core հավելվածների գործարկման ժամանակը:
  • 2.2 տարբերակով հայտնվեց Tier Compilation-ը, որի շնորհիվ ծրագրավորողները ավելի քիչ ժամանակ կծախսեն նախագծի մեկնարկի վրա։
  • Աջակցություն նոր .NET ստանդարտներին:
  • Աջակցություն ծրագրավորման լեզվի նոր տարբերակին:
  • Օպտիմալացում, յուրաքանչյուր նոր տարբերակի հետ բարելավվում է բազային գրադարանների Collection/Struct/Stream/String/Regex և շատ ավելին օպտիմալացում: Եթե ​​դուք տեղափոխվում եք .NET Framework-ից դեպի .NET Core, դուք կստանաք կատարողականի մեծ խթան: Որպես օրինակ, ես հղում եմ կցում որոշ օպտիմալացումների, որոնք ավելացվել են .NET Core 3.0-ում: https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/

Կատարում .NET Core-ում

Ամփոփում

Կոդ գրելիս արժե ուշադրություն դարձնել ձեր նախագծի տարբեր կողմերին և օգտագործել ձեր ծրագրավորման լեզվի և հարթակի առանձնահատկությունները՝ լավագույն արդյունքի հասնելու համար: Ուրախ կլինեմ, եթե օպտիմիզացման հետ կապված ձեր գիտելիքները կիսեք .NET-ում:

Հղում դեպի github

Source: www.habr.com

Добавить комментарий