Perfformiad yn .NET Core

Perfformiad yn .NET Core

Perfformiad yn .NET Core

Helo pawb! Mae'r erthygl hon yn gasgliad o Arferion Gorau y mae fy nghydweithwyr a minnau wedi bod yn eu defnyddio ers amser maith wrth weithio ar wahanol brosiectau.

Gwybodaeth am y peiriant y gwnaed y cyfrifiadau arno:BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-8250U CPU 1.60GHz (Kaby Lake R), 1 CPU, 8 craidd rhesymegol a 4 craidd corfforol
.NET Craidd SDK=3.0.100
[Gwesteiwr]: .NET Core 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), 64bit RyuJIT
Craidd: .NET Core 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), 64bit RyuJIT
[Gwesteiwr]: .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT
Craidd: .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT

Swydd=Amser Rhedeg Craidd=Craidd

ToList vs ToArray a Cycles


Roeddwn i'n bwriadu paratoi'r wybodaeth hon gyda rhyddhau .NET Core 3.0, ond fe wnaethon nhw fy nghuro i, nid wyf am ddwyn gogoniant rhywun arall a chopïo gwybodaeth pobl eraill, felly byddaf yn nodi dolen i erthygl dda lle disgrifir y gymhariaeth yn fanwl.

Ar fy rhan fy hun, rwyf am gyflwyno fy mesuriadau a'm canlyniadau i chi; ychwanegais ddolennau cefn atynt ar gyfer y rhai sy'n hoff o'r “arddull C ++” o ddolenni ysgrifennu.

Côd:

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

Mae cyflymderau perfformiad yn .NET Core 2.2 a 3.0 bron yn union yr un fath. Dyma beth roeddwn i'n gallu ei gael yn .NET Core 3.0:

Perfformiad yn .NET Core

Perfformiad yn .NET Core

Gallwn ddod i'r casgliad bod prosesu iteraidd casgliad Array yn gyflymach oherwydd ei optimeiddio mewnol a'i ddyraniad penodol o ran maint y casgliad. Mae hefyd yn werth cofio bod gan gasgliad Rhestr ei fanteision ei hun a dylech ddefnyddio'r casgliad cywir yn dibynnu ar y cyfrifiadau sydd eu hangen. Hyd yn oed os ydych chi'n ysgrifennu rhesymeg ar gyfer gweithio gyda dolenni, peidiwch ag anghofio mai dolen gyffredin yw hon ac mae hefyd yn destun optimeiddio dolen bosibl. Cyhoeddwyd erthygl ar habr amser maith yn ôl: https://habr.com/ru/post/124910/. Mae'n dal yn berthnasol ac yn ddeunydd darllen a argymhellir.

Taflwch

Flwyddyn yn ôl, bûm yn gweithio mewn cwmni ar brosiect etifeddiaeth, ac yn y prosiect hwnnw roedd yn arferol prosesu dilysiad maes trwy luniad ceisio dal-taflu. Deallais yn barod bryd hynny mai rhesymeg fusnes afiach oedd hon ar gyfer y prosiect, felly ceisiais beidio â defnyddio dyluniad o'r fath pryd bynnag y bo modd. Ond gadewch i ni ddarganfod pam mae'r dull o drin gwallau gydag adeiladwaith o'r fath yn ddrwg. Ysgrifennais god bach i gymharu'r ddau ddull a gwneud meincnodau ar gyfer pob opsiwn.

Côd:

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

Mae'r canlyniadau yn .NET Core 3.0 a Core 2.2 yn cael canlyniad tebyg (. NET Core 3.0):

Perfformiad yn .NET Core

Perfformiad yn .NET Core

Ceisiwch ddal yn gwneud y cod yn anoddach ei ddeall ac yn cynyddu amser gweithredu eich rhaglen. Ond os oes angen y lluniad hwn arnoch, ni ddylech fewnosod y llinellau cod hynny na ddisgwylir iddynt drin gwallau - bydd hyn yn gwneud y cod yn haws ei ddeall. Mewn gwirionedd, nid ymdrin ag eithriadau sy'n llwytho'r system i raddau helaeth, ond yn hytrach taflu gwallau eu hunain drwy'r adeiladwaith Eithriad newydd.

Mae taflu eithriadau yn arafach na rhai dosbarth a fydd yn casglu'r gwall yn y fformat gofynnol. Os ydych yn prosesu ffurflen neu rywfaint o ddata a'ch bod yn amlwg yn gwybod beth ddylai'r gwall fod, beth am ei brosesu?

Ni ddylech ysgrifennu lluniad Eithriad() tafliad newydd os nad yw'r sefyllfa hon yn eithriadol. Mae trin a thaflu eithriad yn ddrud iawn !!!

ToLower, ToLowerInvariant, ToUpper, ToUpperInvariant

Dros fy 5 mlynedd o brofiad yn gweithio ar y llwyfan .NET, rwyf wedi dod ar draws llawer o brosiectau a ddefnyddiodd baru llinynnau. Gwelais y llun canlynol hefyd: roedd un datrysiad Menter gyda llawer o brosiectau, pob un ohonynt yn perfformio cymariaethau llinynnol yn wahanol. Ond beth ddylid ei ddefnyddio a sut i'w uno? Yn y llyfr CLR trwy C# gan Richter, darllenais wybodaeth bod y dull ToUpperInvariant() yn gyflymach na ToLowerInvariant().

Dyfyniad o'r llyfr:

Perfformiad yn .NET Core

Wrth gwrs, doeddwn i ddim yn ei gredu a phenderfynais redeg rhai profion wedyn ar y Fframwaith .NET ac fe wnaeth y canlyniad fy synnu - mwy na chynnydd perfformiad 15%. Yna, ar ôl cyrraedd y gwaith y bore wedyn, dangosais y mesuriadau hyn i'm swyddogion uwch a rhoi mynediad iddynt at y cod ffynhonnell. Ar ôl hyn, newidiwyd 2 allan o 14 prosiect i ddarparu ar gyfer y mesuriadau newydd, ac o ystyried bod y ddau brosiect hyn yn bodoli i brosesu tablau Excel enfawr, roedd y canlyniad yn fwy nag arwyddocaol ar gyfer y cynnyrch.

Rwyf hefyd yn cyflwyno mesuriadau i chi ar gyfer gwahanol fersiynau o .NET Core, fel y gall pob un ohonoch wneud dewis tuag at yr ateb mwyaf optimaidd. Ac yr wyf am ychwanegu yn y cwmni lle rwy'n gweithio, rydym yn defnyddio ToUpper () i gymharu llinynnau.

Côd:

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

Perfformiad yn .NET Core

Perfformiad yn .NET Core

Yn .NET Core 3.0, y cynnydd ar gyfer pob un o'r dulliau hyn yw ~x2 ac mae'n cydbwyso'r gweithrediadau ymhlith ei gilydd.

Perfformiad yn .NET Core

Perfformiad yn .NET Core

Casgliad Haen

Yn fy erthygl ddiwethaf disgrifiais y swyddogaeth hon yn fyr, hoffwn gywiro ac ychwanegu at fy ngeiriau. Mae crynhoad aml-lefel yn cyflymu amser cychwyn eich datrysiad, ond rydych chi'n aberthu y bydd rhannau o'ch cod yn cael eu llunio i fersiwn mwy optimaidd yn y cefndir, a all gyflwyno gorbenion bach. Gyda dyfodiad NET Core 3.0, mae'r amser adeiladu ar gyfer prosiectau gyda chrynhoad haen wedi'i alluogi wedi lleihau ac mae bygiau sy'n gysylltiedig â'r dechnoleg hon wedi'u trwsio. Yn flaenorol, arweiniodd y dechnoleg hon at wallau yn y ceisiadau cyntaf yn ASP.NET Core ac yn rhewi yn ystod y cyfnod adeiladu cyntaf yn y modd llunio aml-lefel. Ar hyn o bryd mae'n cael ei alluogi yn ddiofyn yn .NET Core 3.0, ond gallwch chi ei analluogi os dymunwch. Os ydych chi mewn sefyllfa arweinydd tîm, uwch, canol, neu os ydych chi'n bennaeth adran, yna mae'n rhaid i chi ddeall bod datblygiad prosiect cyflym yn cynyddu gwerth y tîm a bydd y dechnoleg hon yn caniatáu ichi arbed amser i'r ddau ddatblygwr. ac amser y prosiect ei hun.

. NET lefel i fyny

Uwchraddio'ch fersiwn .NET Framework / .NET Core. Yn aml, mae pob fersiwn newydd yn darparu enillion perfformiad ychwanegol ac yn ychwanegu nodweddion newydd.

Ond beth yn union yw'r manteision? Edrychwn ar rai ohonynt:

  • Cyflwynodd .NET Core 3.0 ddelweddau R2R a fydd yn lleihau amser cychwyn cymwysiadau .NET Core.
  • Gyda fersiwn 2.2, ymddangosodd Haen Compilation, diolch i ba raglenwyr fydd yn treulio llai o amser yn lansio prosiect.
  • Cefnogaeth i Safonau NET newydd.
  • Cefnogaeth i fersiwn newydd o'r iaith raglennu.
  • Optimeiddio, gyda phob fersiwn newydd mae optimeiddio Casgliad / Strwythur / Ffrwd / Llinyn / Regex y llyfrgelloedd sylfaenol a llawer mwy yn gwella. Os ydych chi'n mudo o'r Fframwaith .NET i .NET Core, fe gewch chi hwb perfformiad mawr allan o'r bocs. Fel enghraifft, rwy'n atodi dolen i rai o'r optimizations a ychwanegwyd at .NET Core 3.0: https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/

Perfformiad yn .NET Core

Casgliad

Wrth ysgrifennu cod, mae'n werth talu sylw i wahanol agweddau ar eich prosiect a defnyddio nodweddion eich iaith raglennu a'ch platfform i gyflawni'r canlyniad gorau. Byddwn yn falch petaech yn rhannu eich gwybodaeth am optimeiddio yn .NET.

Dolen i github

Ffynhonnell: hab.com

Ychwanegu sylw