Errendimendua .NET Core-n

Errendimendua .NET Core-n

Errendimendua .NET Core-n

Kaixo guztioi! Artikulu hau nire lankideek eta biok proiektu ezberdinetan lan egiten ari garenean aspalditik erabiltzen ari garen Praktika Onen bilduma bat da.

Kalkuluak egin diren makinari buruzko informazioa:BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-8250U CPU 1.60 GHz (Kaby Lake R), CPU 1, 8 nukleo logiko eta 4 fisiko
.NET Core SDK=3.0.100
[Ostalaria]: .NET Core 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), 64 biteko RyuJIT
Nukleoa: .NET Core 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), 64 biteko RyuJIT
[Ostalaria]: .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64 biteko RyuJIT
Nukleoa: .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64 biteko RyuJIT

Job=Nukleoa Runtime=Nukleoa

ToList vs ToArray eta Cycles


Informazio hau .NET Core 3.0 bertsioarekin prestatzeko asmoa nuen, baina irabazi egin ninduten, ez dut nahi beste norbaiten aintza lapurtu eta besteen informazioa kopiatu nahi, beraz, adieraziko dut. esteka artikulu on batera non konparazioa zehatz-mehatz deskribatzen den.

Nire izenean, nire neurketak eta emaitzak aurkeztu nahi dizkizuet; alderantzizko begiztak gehitu nizkion idazteko begiztak "C++ estiloa" zaleentzat.

kodea:

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 eta 3.0-en errendimendu-abiadurak ia berdinak dira. Hona hemen .NET Core 3.0-n lortu ahal izan dudana:

Errendimendua .NET Core-n

Errendimendua .NET Core-n

Array bilduma baten prozesamendu iteratiboa azkarragoa dela ondoriozta dezakegu, barne optimizazioengatik eta bildumaren tamaina esleipen esplizituagatik. Gogoratu behar da Zerrenda-bilduma batek bere abantailak dituela eta bilduma egokia erabili behar duzula behar diren kalkuluen arabera. Bezpilekin lan egiteko logika idazten baduzu ere, ez ahaztu begizta arrunta dela eta begizta posibleen optimizazioaren menpe dagoela. Artikulu bat argitaratu zen habr-en duela denbora asko: https://habr.com/ru/post/124910/. Irakurketa garrantzitsua eta gomendagarria da oraindik.

Bota

Duela urtebete, enpresa batean lan egin nuen ondare-proiektu batean, proiektu horretan normala zen eremuaren baliozkotzea try-catch-throw eraikuntza baten bidez prozesatzea. Dagoeneko ulertu nuen orduan hori proiekturako negozio-logika osasuntsua zela, beraz, ahal zen guztietan horrelako diseinurik ez erabiltzen saiatu nintzen. Baina ikus dezagun zergatik den txarra horrelako eraikuntza batekin akatsak kudeatzeko planteamendua. Kode txiki bat idatzi nuen bi ikuspegiak alderatzeko eta aukera bakoitzerako erreferentziak egin nituen.

kodea:

        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 eta Core 2.2-en emaitzek antzeko emaitza dute (.NET Core 3.0):

Errendimendua .NET Core-n

Errendimendua .NET Core-n

Saiatu catch-ek kodea ulertzeko zailagoa egiten du eta zure programaren exekuzio-denbora handitzen du. Baina eraikuntza hau behar baduzu, ez dituzu akatsak kudeatzeko espero ez diren kode-lerro horiek txertatu behar; horrek kodea ulertzea erraztuko du. Izan ere, ez da salbuespenen kudeaketa sistema kargatzen duena, baizik eta erroreak botatzea Salbuespen berriaren eraikuntzaren bidez.

Salbuespenak botatzea akatsa eskatutako formatuan bilduko duten klase batzuk baino motelagoa da. Inprimaki bat edo datu batzuk prozesatzen ari bazara eta argi eta garbi badakizu zein izan behar den errorea, zergatik ez prozesatu?

Ez zenuke Exception() eraikuntza berririk idatzi behar egoera hau apartekoa ez bada. Salbuespen bat maneiatzea eta botatzea oso garestia da!!!

ToLower, ToLowerInvariant, ToUpper, ToUpperInvariant

.NET plataforman lan egiten dudan 5 urteko esperientzian zehar, kateen parekatzea erabiltzen zuten proiektu askorekin egin dut topo. Irudi hau ere ikusi nuen: bazegoen Enterprise irtenbide bat proiektu askorekin, eta bakoitzak modu ezberdinean egiten zituen kateen konparaketak. Baina zer erabili behar da eta nola bateratu? Richter-en CLR bidez C# liburuan ToUpperInvariant() metodoa ToLowerInvariant() baino azkarragoa dela dioen informazioa irakurri dut.

Liburuaren zatia:

Errendimendua .NET Core-n

Noski, ez nuen sinetsi eta proba batzuk egitea erabaki nuen .NET Framework-en eta emaitzak harritu ninduen: errendimenduaren % 15 baino gehiago igo zen. Gero, hurrengo goizean lanera iristean, neurketa hauek nire nagusiei erakutsi nizkion eta iturri-koderako sarbidea eman nien. Horren ostean, 2 proiektutik 14 aldatu ziren neurketa berrietara egokitzeko, eta bi proiektu hauek Excel taula erraldoiak prozesatzeko existitzen zirela kontuan hartuta, emaitza esanguratsuagoa izan zen produktuarentzat.

.NET Core-ren bertsio ezberdinen neurketak ere aurkezten dizkizut, zuetako bakoitzak irtenbiderik onenaren aldeko hautua egin dezan. Eta gehitu nahi dut lan egiten dudan enpresan ToUpper() erabiltzen dugula kateak alderatzeko.

kodea:

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

Errendimendua .NET Core-n

Errendimendua .NET Core-n

.NET Core 3.0-n, metodo hauetako bakoitzaren igoera ~x2 da eta inplementazioak orekatzen ditu haien artean.

Errendimendua .NET Core-n

Errendimendua .NET Core-n

Maila-bilketa

Nire azken artikuluan funtzionalitate hau labur deskribatu nuen, nire hitzak zuzendu eta osatu nahiko nituzke. Maila anitzeko konpilazioak zure soluzioaren abiarazte-denbora bizkortzen du, baina zure kodearen zatiak atzeko planoan bertsio optimizatuago batean konpilatuko direla sakrifikatzen duzu, eta horrek gastu txiki bat sor dezake. NET Core 3.0 agertzearekin batera, maila-konpilazioa gaituta duten proiektuen eraikuntza-denbora murriztu egin da eta teknologia honekin lotutako akatsak konpondu dira. Aurretik, teknologia honek akatsak eragin zituen ASP.NET Core-ko lehen eskaeretan eta izoztu egiten da maila anitzeko konpilazio moduan lehen eraikuntzan. Une lehenespenez gaituta dago .NET Core 3.0-n, baina nahi izanez gero desgai dezakezu. Talde-buru, senior, erdiko edo sail bateko burua bazara, ulertu behar duzu proiektuaren garapen azkarrak taldearen balioa handitzen duela eta teknologia honek bi garatzaileentzako denbora aurrezteko aukera emango dizu. eta proiektuaren ordua bera.

.NET maila igotzea

Berritu zure .NET Framework / .NET Core bertsioa. Sarritan, bertsio berri bakoitzak errendimendu-irabazi gehigarriak eskaintzen ditu eta funtzio berriak gehitzen ditu.

Baina zeintzuk dira zehazki onurak? Ikus ditzagun horietako batzuk:

  • .NET Core 3.0-k .NET Core aplikazioen abiarazte-denbora murriztuko duten R2R irudiak sartu zituen.
  • 2.2 bertsioarekin, Tier Compilation agertu zen, eta horri esker programatzaileek denbora gutxiago emango dute proiektu bat abiarazten.
  • .NET Estandar berrietarako laguntza.
  • Programazio-lengoaiaren bertsio berrirako laguntza.
  • Optimizazioa, bertsio berri bakoitzean oinarrizko liburutegien optimizazioa Collection/Struct/Stream/String/Regex eta askoz gehiago hobetzen da. .NET Framework-etik .NET Core-ra migratzen ari bazara, errendimenduaren sustapen handia lortuko duzu. Adibide gisa, .NET Core 3.0-ra gehitu ziren optimizazio batzuetarako esteka bat eransten dut: https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/

Errendimendua .NET Core-n

Ondorioa

Kodea idaztean, merezi du zure proiektuaren hainbat alderdiri erreparatzea eta zure programazio-lengoaia eta plataformaren ezaugarriak erabiltzea emaitza onena lortzeko. Pozik egongo nintzateke .NET-en optimizazioarekin lotutako ezagutzak partekatzen badituzu.

Github-erako esteka

Iturria: www.habr.com

Gehitu iruzkin berria