Erthygl aflwyddiannus am gyflymu myfyrio

Byddaf yn egluro teitl yr erthygl ar unwaith. Y cynllun gwreiddiol oedd rhoi cyngor da, dibynadwy ar sut i gyflymu’r defnydd o fyfyrio gan ddefnyddio enghraifft syml ond realistig, ond wrth feincnodi daeth i’r amlwg nad yw myfyrio mor araf ag y tybiais, mae LINQ yn arafach nag yn fy hunllefau. Ond yn y diwedd daeth i'r amlwg fy mod hefyd wedi gwneud camgymeriad yn y mesuriadau ... Mae manylion y stori bywyd hon o dan y toriad ac yn y sylwadau. Gan fod yr enghraifft yn eithaf cyffredin ac yn cael ei weithredu mewn egwyddor fel sy'n cael ei wneud fel arfer mewn menter, daeth yn arddangosiad eithaf diddorol, fel y mae'n ymddangos i mi, o fywyd: yr effaith ar gyflymder prif bwnc yr erthygl oedd ddim yn amlwg oherwydd rhesymeg allanol: Moq, Autofac, EF Core ac eraill "strapiau".

Dechreuais weithio o dan argraff yr erthygl hon: Pam fod Myfyrdod yn araf

Fel y gallwch weld, mae'r awdur yn awgrymu defnyddio cynrychiolwyr a luniwyd yn lle galw'n uniongyrchol ddulliau math o fyfyrio fel ffordd wych o gyflymu'r cais yn fawr. Mae yna, wrth gwrs, allyriadau IL, ond hoffwn ei osgoi, gan mai dyma'r ffordd fwyaf llafurddwys i gyflawni'r dasg, sy'n llawn gwallau.

O ystyried fy mod bob amser wedi bod â barn debyg am gyflymder y myfyrio, nid oeddwn yn bwriadu cwestiynu casgliadau’r awdur yn benodol.

Rwy'n aml yn dod ar draws defnydd naïf o fyfyrio yn y fenter. Cymerir y math. Cymerir gwybodaeth am yr eiddo. Gelwir y dull SetValue ac mae pawb yn llawenhau. Mae'r gwerth wedi cyrraedd y maes targed, mae pawb yn hapus. Mae pobl glyfar iawn - pobl hŷn ac arweinwyr tîm - yn ysgrifennu eu hestyniadau i wrthrych, gan seilio ar weithrediad mor naïf mapwyr “cyffredinol” o un math i'r llall. Y hanfod fel arfer yw hyn: rydym yn cymryd yr holl feysydd, yn cymryd yr holl briodweddau, yn ailadrodd drostynt: os yw enwau'r aelodau math yn cyfateb, rydym yn gweithredu SetValue. O bryd i'w gilydd rydym yn dal eithriadau oherwydd camgymeriadau lle na wnaethom ddod o hyd i rywfaint o eiddo yn un o'r mathau, ond hyd yn oed yma mae ffordd allan sy'n gwella perfformiad. Ceisiwch/dal.

Rwyf wedi gweld pobl yn ailddyfeisio parsers a mapwyr heb fod yn gwbl arfog â gwybodaeth am sut mae'r peiriannau a ddaeth o'u blaenau yn gweithio. Rwyf wedi gweld pobl yn cuddio eu gweithrediadau naïf y tu ôl i strategaethau, y tu ôl i ryngwynebau, y tu ôl i bigiadau, fel pe bai hyn yn esgusodi'r bacchanalia dilynol. Troais fy nhrwyn i fyny at sylweddoliadau o'r fath. A dweud y gwir, ni wnes i fesur y gollyngiad perfformiad gwirioneddol, ac, os yn bosibl, fe wnes i newid y gweithrediad i un mwy “optimaidd” pe gallwn gael fy nwylo arno. Felly, roedd y mesuriadau cyntaf a drafodir isod wedi fy nrysu’n ddifrifol.

Rwy'n meddwl bod llawer ohonoch, sy'n darllen Richter neu ideolegwyr eraill, wedi dod ar draws datganiad cwbl deg bod myfyrio mewn cod yn ffenomen sy'n cael effaith hynod negyddol ar berfformiad y cais.

Mae galw myfyrdod yn gorfodi'r CLR i fynd trwy wasanaethau i ddod o hyd i'r un sydd ei angen arnynt, tynnu eu metadata i fyny, eu dosrannu, ac ati. Yn ogystal, mae myfyrio wrth groesi dilyniannau yn arwain at ddyrannu llawer iawn o gof. Rydym yn defnyddio cof, mae CLR yn datgelu'r GC ac mae ffrisiau'n dechrau. Dylai fod yn amlwg yn araf, credwch fi. Nid yw'r symiau enfawr o gof ar weinyddion cynhyrchu modern neu beiriannau cwmwl yn atal oedi prosesu uchel. Mewn gwirionedd, po fwyaf o gof, y mwyaf tebygol ydych chi o HYSBYSIAD sut mae'r GC yn gweithio. Mae myfyrio, mewn theori, yn glwt coch ychwanegol iddo.

Fodd bynnag, rydym i gyd yn defnyddio cynwysyddion IoC a mapwyr dyddiad, y mae eu hegwyddor gweithredu hefyd yn seiliedig ar adlewyrchiad, ond fel arfer nid oes unrhyw gwestiynau am eu perfformiad. Na, nid oherwydd bod cyflwyno dibyniaethau a thynnu o fodelau cyd-destun cyfyngedig allanol mor angenrheidiol fel bod yn rhaid inni aberthu perfformiad beth bynnag. Mae popeth yn symlach - nid yw'n effeithio llawer ar berfformiad.

Y ffaith yw bod y fframweithiau mwyaf cyffredin sy'n seiliedig ar dechnoleg adfyfyrio yn defnyddio pob math o driciau i weithio gydag ef yn fwy optimaidd. Fel arfer celc yw hwn. Yn nodweddiadol mae'r rhain yn Ymadroddion a chynrychiolwyr wedi'u casglu o'r goeden fynegiant. Mae'r un automapper yn cynnal geiriadur cystadleuol sy'n cyfateb mathau â swyddogaethau a all drosi un yn un arall heb alw adlewyrchiad.

Sut y cyflawnir hyn? Yn y bôn, nid yw hyn yn wahanol i'r rhesymeg y mae'r platfform ei hun yn ei defnyddio i gynhyrchu cod JIT. Pan elwir dull am y tro cyntaf, caiff ei lunio (ac, ie, nid yw'r broses hon yn gyflym); ar alwadau dilynol, trosglwyddir rheolaeth i'r dull a luniwyd eisoes, ac ni fydd unrhyw ostyngiadau perfformiad sylweddol.

Yn ein hachos ni, gallwch hefyd ddefnyddio casgliad JIT ac yna defnyddio'r ymddygiad a luniwyd gyda'r un perfformiad â'i gymheiriaid AOT. Daw mynegiadau i'n cynorthwyo yn yr achos hwn.

Gellir llunio'r egwyddor dan sylw yn gryno fel a ganlyn:
Dylech storio canlyniad terfynol y myfyrdod fel dirprwy sy'n cynnwys y swyddogaeth a luniwyd. Mae hefyd yn gwneud synnwyr i storio'r holl wrthrychau angenrheidiol gyda gwybodaeth math yn y meysydd o'ch math chi, y gweithiwr, sy'n cael eu storio y tu allan i'r gwrthrychau.

Mae rhesymeg yn hyn. Mae synnwyr cyffredin yn dweud wrthym, os gellir casglu a storio rhywbeth, yna dylid ei wneud.

Wrth edrych ymlaen, dylid dweud bod gan y storfa wrth weithio gydag adlewyrchiad ei fanteision, hyd yn oed os na ddefnyddiwch y dull arfaethedig o lunio ymadroddion. A dweud y gwir, dyma fi'n ailadrodd traethodau ymchwil awdur yr erthygl y cyfeiriaf ati uchod.

Nawr am y cod. Gadewch i ni edrych ar enghraifft sy'n seiliedig ar fy mhoen diweddar y bu'n rhaid i mi ei hwynebu mewn cynhyrchiad difrifol o sefydliad credyd difrifol. Mae pob endid yn ffug fel na fyddai neb yn dyfalu.

Mae rhywfaint o hanfod. Gadewch fod Cyswllt. Mae yna lythyrau gyda chorff safonol, ac o'r rhain mae'r parser a'r hydrator yn creu'r un cysylltiadau hyn. Cyrhaeddodd llythyr, fe wnaethom ei ddarllen, ei ddosrannu'n barau gwerth allweddol, creu cyswllt, a'i gadw yn y gronfa ddata.

Mae'n elfennol. Gadewch i ni ddweud bod gan gyswllt yr eiddo Enw Llawn, Oedran a Ffôn Cyswllt. Mae'r data hwn yn cael ei drosglwyddo yn y llythyr. Mae'r busnes hefyd eisiau cymorth i allu ychwanegu allweddi newydd yn gyflym ar gyfer mapio eiddo endid yn barau yng nghorff y llythyr. Rhag ofn i rywun wneud teipio yn y templed neu os cyn y datganiad mae angen lansio mapio gan bartner newydd ar frys, gan addasu i'r fformat newydd. Yna gallwn ychwanegu cydberthynas mapio newydd fel atgyweiriad data rhad. Hynny yw, enghraifft bywyd.

Rydym yn gweithredu, yn creu profion. Yn gweithio.

Ni fyddaf yn darparu'r cod: mae yna lawer o ffynonellau, ac maen nhw ar gael ar GitHub trwy'r ddolen ar ddiwedd yr erthygl. Gallwch eu llwytho, eu harteithio y tu hwnt i adnabyddiaeth a'u mesur, fel y byddai'n effeithio yn eich achos chi. Ni roddaf ond cod dau ddull templed sy'n gwahaniaethu'r hydrator, a oedd i fod i fod yn gyflym, oddi wrth y hydradwr, a oedd i fod i fod yn araf.

Mae'r rhesymeg fel a ganlyn: mae'r dull templed yn derbyn parau a gynhyrchir gan y rhesymeg parser sylfaenol. Yr haen LINQ yw'r parser a rhesymeg sylfaenol yr hydrator, sy'n gwneud cais i gyd-destun y gronfa ddata ac yn cymharu allweddi â pharau o'r parser (ar gyfer y swyddogaethau hyn mae cod heb LINQ i'w gymharu). Nesaf, trosglwyddir y parau i'r prif ddull hydradu a gosodir gwerthoedd y parau i briodweddau cyfatebol yr endid.

“Cyflym” (Rhagddodiad Cyflym mewn meincnodau):

 protected override Contact GetContact(PropertyToValueCorrelation[] correlations)
        {
            var contact = new Contact();
            foreach (var setterMapItem in _proprtySettersMap)
            {
                var correlation = correlations.FirstOrDefault(x => x.PropertyName == setterMapItem.Key);
                setterMapItem.Value(contact, correlation?.Value);
            }
            return contact;
        }

Fel y gallwn weld, defnyddir casgliad sefydlog gyda phriodweddau setter - lambdas wedi'i lunio sy'n galw'r endid gosodwr. Wedi'i greu gan y cod canlynol:

        static FastContactHydrator()
        {
            var type = typeof(Contact);
            foreach (var property in type.GetProperties())
            {
                _proprtySettersMap[property.Name] = GetSetterAction(property);
            }
        }

        private static Action<Contact, string> GetSetterAction(PropertyInfo property)
        {
            var setterInfo = property.GetSetMethod();
            var paramValueOriginal = Expression.Parameter(property.PropertyType, "value");
            var paramEntity = Expression.Parameter(typeof(Contact), "entity");
            var setterExp = Expression.Call(paramEntity, setterInfo, paramValueOriginal).Reduce();
            
            var lambda = (Expression<Action<Contact, string>>)Expression.Lambda(setterExp, paramEntity, paramValueOriginal);

            return lambda.Compile();
        }

Yn gyffredinol, mae'n glir. Rydym yn croesi'r eiddo, yn creu cynrychiolwyr ar eu cyfer sy'n galw gosodwyr, ac yn eu hachub. Yna rydym yn galw pan fo angen.

“Araf” (Rhagddodiad Araf mewn meincnodau):

        protected override Contact GetContact(PropertyToValueCorrelation[] correlations)
        {
            var contact = new Contact();
            foreach (var property in _properties)
            {
                var correlation = correlations.FirstOrDefault(x => x.PropertyName == property.Name);
                if (correlation?.Value == null)
                    continue;

                property.SetValue(contact, correlation.Value);
            }
            return contact;
        }

Yma rydym yn osgoi'r eiddo ar unwaith ac yn galw SetValue yn uniongyrchol.

Er eglurder ac fel cyfeiriad, gweithredais ddull naïf sy'n ysgrifennu gwerthoedd eu parau cydberthynas yn uniongyrchol i'r meysydd endid. Rhagddodiad - Llawlyfr.

Nawr, gadewch i ni gymryd BenchmarkDotNet ac archwilio'r perfformiad. Ac yn sydyn... (difethwr - nid dyma'r canlyniad cywir, mae'r manylion isod)

Erthygl aflwyddiannus am gyflymu myfyrio

Beth welwn ni yma? Mae dulliau sy'n dwyn y rhagddodiad Cyflym yn fuddugoliaethus yn troi allan yn arafach ym mron pob pas na dulliau gyda'r rhagddodiad Araf. Mae hyn yn wir ar gyfer dyraniad a chyflymder y gwaith. Ar y llaw arall, mae gweithredu mapio hardd a chain gan ddefnyddio dulliau LINQ a fwriedir ar gyfer hyn lle bynnag y bo modd, i'r gwrthwyneb, yn lleihau cynhyrchiant yn fawr. Mae'r gwahaniaeth o drefn. Nid yw'r duedd yn newid gyda gwahanol niferoedd o docynnau. Yr unig wahaniaeth yw maint. Gyda LINQ mae 4 - 200 gwaith yn arafach, mae mwy o sothach ar yr un raddfa fwy neu lai.

DIWEDDARWYD

Doeddwn i ddim yn credu fy llygaid, ond yn bwysicach fyth, nid oedd ein cydweithiwr yn credu naill ai fy llygaid na fy nghod - Dmitry Tikhonov 0x1000000. Ar ôl gwirio fy ateb ddwywaith, darganfu'n wych a thynnodd sylw at wall yr oeddwn wedi'i golli oherwydd nifer o newidiadau yn y broses weithredu, o'r dechrau i'r diwedd. Ar ôl trwsio'r byg a ganfuwyd yn y gosodiad Moq, daeth yr holl ganlyniadau i'w lle. Yn ôl canlyniadau'r ailbrawf, nid yw'r prif duedd yn newid - mae LINQ yn dal i effeithio ar berfformiad yn fwy na myfyrio. Fodd bynnag, mae'n braf nad yw'r gwaith gyda chrynhoi Mynegiant yn cael ei wneud yn ofer, ac mae'r canlyniad yn weladwy o ran amser dyrannu a gweithredu. Mae'r lansiad cyntaf, pan fydd meysydd sefydlog yn cael eu cychwyn, yn naturiol yn arafach ar gyfer y dull “cyflym”, ond yna mae'r sefyllfa'n newid.

Dyma ganlyniad yr ail brawf:

Erthygl aflwyddiannus am gyflymu myfyrio

Casgliad: wrth ddefnyddio adlewyrchiad mewn menter, nid oes angen troi at driciau yn benodol - bydd LINQ yn bwyta cynhyrchiant yn fwy. Fodd bynnag, mewn dulliau llwyth uchel sy'n gofyn am optimeiddio, gallwch arbed adlewyrchiad ar ffurf cychwynwyr a chasglwyr cynrychiolwyr, a fydd wedyn yn darparu rhesymeg “cyflym”. Fel hyn gallwch chi gynnal hyblygrwydd adlewyrchiad a chyflymder y cais.

Mae'r cod meincnod ar gael yma. Gall unrhyw un wirio fy ngeiriau ddwywaith:
Profion Myfyrdod Habra

PS: mae'r cod yn y profion yn defnyddio IoC, ac yn y meincnodau mae'n defnyddio lluniad penodol. Y ffaith yw fy mod, yn y gweithrediad terfynol, wedi torri i ffwrdd yr holl ffactorau a allai effeithio ar berfformiad a gwneud y canlyniad yn swnllyd.

PPS: Diolch i'r defnyddiwr Dmitry Tikhonov @0x1000000 am ddarganfod fy gwall wrth sefydlu Moq, a effeithiodd ar y mesuriadau cyntaf. Os oes gan unrhyw un o'r darllenwyr ddigon o karma, hoffwch ef. Stopiodd y dyn, darllenodd y dyn, gwiriodd y dyn ddwywaith a thynnu sylw at y camgymeriad. Rwy'n meddwl bod hyn yn haeddu parch a chydymdeimlad.

PPPS: diolch i'r darllenydd manwl gywir a gyrhaeddodd waelod yr arddull a'r dyluniad. Rwyf am unffurfiaeth a chyfleustra. Mae diplomyddiaeth y cyflwyniad yn gadael llawer i'w ddymuno, ond cymerais y feirniadaeth i ystyriaeth. Gofynnaf am y projectile.

Ffynhonnell: hab.com

Ychwanegu sylw