.NET Core жүйесіндегі өнімділік

.NET Core жүйесіндегі өнімділік

.NET Core жүйесіндегі өнімділік

Бәріңе сәлем! Бұл мақала әртүрлі жобалармен жұмыс істеу кезінде менің әріптестеріммен ұзақ уақыт бойы қолданып келе жатқан үздік тәжірибелер жинағы.

Есептеулер жүргізілген машина туралы ақпарат:BenchmarkDotNet=v0.11.5, ОЖ=Windows 10.0.18362
Intel Core i5-8250U CPU 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 шығарылымымен дайындауды жоспарладым, бірақ олар мені жеңді, мен басқа біреудің даңқын ұрлап, басқа адамдардың ақпаратын көшіргім келмейді, сондықтан мен жай ғана атап өткім келеді. салыстыру егжей-тегжейлі сипатталған жақсы мақалаға сілтеме.

Өз атымнан мен сіздерге өзімнің өлшемдерім мен нәтижелерімді ұсынғым келеді; «С++ стилін» жазу ілмектерін ұнататындар үшін мен оларға кері циклдар қостым.

Код:

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 жүйесіндегі өнімділік

Массив топтамасын итерациялық өңдеу оның ішкі оңтайландырулары мен нақты жинақ өлшемін бөлудің арқасында жылдамырақ деген қорытындыға келуге болады. Сондай-ақ, List топтамасының өзіндік артықшылықтары бар екенін және қажетті есептеулерге байланысты дұрыс жинақты пайдалану керек екенін есте ұстаған жөн. Егер сіз циклдармен жұмыс істеу логикасын жазсаңыз да, бұл қарапайым цикл екенін және ол циклды оңтайландыруға болатынын ұмытпаңыз. Баяғыда habr сайтында мақала жарияланған: https://habr.com/ru/post/124910/. Ол әлі де өзекті және оқуға ұсынылады.

Лақтыру

Бір жыл бұрын мен компанияда бұрынғы жобада жұмыс істедім, бұл жобада далалық тексеруді try-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 жүйесіндегі өнімділік

Ұстап көріңіз кодты түсінуді қиындатады және бағдарламаңыздың орындалу уақытын арттырады. Бірақ егер сізге бұл құрылыс қажет болса, қателерді өңдей алмайтын код жолдарын кірістірмеу керек - бұл кодты түсінуді жеңілдетеді. Шындығында, жүйені жүктейтін ерекше жағдайларды өңдеу емес, керісінше, throw жаңа Ерекшелік конструкциясы арқылы қателерді жіберу.

Ерекшеліктерді шығару қатені қажетті пішімде жинайтын кейбір сыныпқа қарағанда баяуырақ. Пішінді немесе кейбір деректерді өңдеп жатсаңыз және қатенің қандай болуы керектігін анық білсеңіз, неге оны өңдемеске?

Бұл жағдай ерекше болмаса, throw new Exception() құрылымын жазбау керек. Ерекше жағдайды өңдеу және тастау өте қымбат!!!

ToLower, ToLowerInvariant, ToUpper, ToUpperInvariant

.NET платформасында жұмыс істеген 5 жылдық тәжірибемде мен жолды сәйкестендіруді пайдаланатын көптеген жобаларды кездестірдім. Мен келесі суретті де көрдім: көптеген жобалары бар бір Enterprise шешімі болды, олардың әрқайсысы жолды салыстыруды басқаша орындады. Бірақ нені пайдалану керек және оны қалай біріктіру керек? Рихтердің C# арқылы CLR кітабында мен 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 .NET Core қолданбаларының іске қосылу уақытын қысқартатын R2R кескіндерін ұсынды.
  • 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 сілтемесі

Ақпарат көзі: www.habr.com

пікір қалдыру