Artiklu bla suċċess dwar l-aċċellerazzjoni tar-riflessjoni

Immedjatament nispjega t-titlu tal-artiklu. Il-pjan oriġinali kien li jagħti pariri tajbin u affidabbli dwar kif tħaffef l-użu tar-riflessjoni bl-użu ta’ eżempju sempliċi iżda realistiku, iżda waqt il-benchmarking irriżulta li r-riflessjoni mhix bil-mod kif ħsibt, LINQ hija aktar bil-mod milli fl-inkubi tiegħi. Imma fl-aħħar irriżulta li għamilt żball ukoll fil-kejl... Dettalji ta’ din l-istorja tal-ħajja jinsabu taħt il-qatgħa u fil-kummenti. Peress li l-eżempju huwa pjuttost komuni u implimentat fil-prinċipju kif normalment isir f'intrapriża, irriżulta li kien pjuttost interessanti, kif jidhirli, dimostrazzjoni tal-ħajja: l-impatt fuq il-veloċità tas-suġġett ewlieni tal-artikolu kien mhux notevoli minħabba loġika esterna: Moq, Autofac, EF Core u oħrajn "ċineg".

Bdejt naħdem taħt l-impressjoni ta' dan l-artikolu: Għaliex ir-Riflessjoni hi bil-mod

Kif tistgħu taraw, l-awtur jissuġġerixxi l-użu ta 'delegati kkumpilati minflok issejjaħ direttament metodi tat-tip ta' riflessjoni bħala mod tajjeb ħafna biex tħaffef ħafna l-applikazzjoni. Hemm, ovvjament, emissjoni IL, imma nixtieq nevitaha, peress li dan huwa l-aktar mod intensiv tax-xogħol biex iwettaq il-kompitu, li huwa mimli żbalji.

Meta wieħed iqis li dejjem kelli opinjoni simili dwar il-ħeffa tar-riflessjoni, ma kellix l-intenzjoni partikolari li niddubita l-konklużjonijiet tal-awtur.

Spiss niltaqa' ma' użu naive tar-riflessjoni fl-intrapriża. It-tip jittieħed. Tittieħed informazzjoni dwar il-proprjetà. Il-metodu SetValue jissejjaħ u kulħadd jifraħ. Il-valur wasal fil-qasam fil-mira, kulħadd huwa kuntent. Nies intelliġenti ħafna - anzjani u mexxejja tat-tim - jiktbu l-estensjonijiet tagħhom biex joġġezzjonaw, ibbażati fuq tali implimentazzjoni naive mappers "universali" ta 'tip għal ieħor. L-essenza hija normalment din: nieħdu l-oqsma kollha, nieħdu l-proprjetajiet kollha, itenni fuqhom: jekk l-ismijiet tal-membri tat-tip jaqblu, aħna tesegwixxi SetValue. Minn żmien għal żmien naqbdu eċċezzjonijiet minħabba żbalji fejn ma sibniex xi proprjetà f’wieħed mit-tipi, iżda anke hawn hemm mod kif toħroġ li ttejjeb il-prestazzjoni. Ipprova/qabda.

Rajt nies jivvintaw mill-ġdid parsers u mappers mingħajr ma jkunu armati bis-sħiħ b'informazzjoni dwar kif jaħdmu l-magni li ġew qabelhom. Rajt nies jaħbu l-implimentazzjonijiet naive tagħhom wara strateġiji, wara interfaces, wara injezzjonijiet, bħallikieku dan jiskuża l-baccanalia sussegwenti. Dawwar imnieħri fuq tali realizzazzjonijiet. Fil-fatt, ma kejlitx it-tnixxija reali tal-prestazzjoni, u, jekk possibbli, sempliċement biddilt l-implimentazzjoni għal waħda aktar "ottimali" jekk stajt nagħmel idejni fuqha. Għalhekk, l-ewwel kejl diskuss hawn taħt ħawwadni serjament.

Naħseb li ħafna minnkom, qraw lil Richter jew ideologisti oħra, iltaqgħu ma 'dikjarazzjoni kompletament ġusta li r-riflessjoni fil-kodiċi hija fenomenu li għandu impatt estremament negattiv fuq il-prestazzjoni tal-applikazzjoni.

Is-sejħa ta 'riflessjoni ġġiegħel lis-CLR jgħaddi minn assemblaġġi biex isibu dak li għandhom bżonn, jiġbdu l-metadata tagħhom, janalizzawhom, eċċ. Barra minn hekk, ir-riflessjoni waqt li jaqsmu s-sekwenzi twassal għall-allokazzjoni ta 'ammont kbir ta' memorja. Qed nużaw il-memorja, CLR jikxef il-GC u jibdew friezes. Għandu jkun notevoli bil-mod, emminni. L-ammonti kbar ta 'memorja fuq servers ta' produzzjoni moderni jew magni tas-sħab ma jipprevjenux dewmien għoli fl-ipproċessar. Fil-fatt, iktar ma jkun hemm memorja, iktar tkun probabbli li tinnota kif jaħdem il-GC. Ir-riflessjoni hija, fit-teorija, rag aħmar żejjed għalih.

Madankollu, aħna lkoll nużaw kontenituri IoC u mappers tad-data, li l-prinċipju operattiv tagħhom huwa wkoll ibbażat fuq riflessjoni, iżda ġeneralment ma jkun hemm l-ebda mistoqsijiet dwar il-prestazzjoni tagħhom. Le, mhux għax l-introduzzjoni tad-dipendenzi u l-astrazzjoni minn mudelli esterni ta' kuntest limitat huma tant meħtieġa li rridu nissagrifikaw il-prestazzjoni fi kwalunkwe każ. Kollox huwa aktar sempliċi - verament ma jaffettwax il-prestazzjoni ħafna.

Il-fatt hu li l-oqfsa l-aktar komuni li huma bbażati fuq teknoloġija ta’ riflessjoni jużaw kull xorta ta’ tricks biex jaħdmu magħha bl-aħjar mod. Normalment dan huwa cache. Tipikament dawn huma Espressjonijiet u delegati miġbura mis-siġra tal-espressjoni. L-istess awtomapper iżomm dizzjunarju kompetittiv li jqabbel it-tipi b'funzjonijiet li jistgħu jikkonvertu wieħed għal ieħor mingħajr ma jsejjaħ riflessjoni.

Kif jinkiseb dan? Essenzjalment, dan mhuwiex differenti mil-loġika li l-pjattaforma nnifisha tuża biex tiġġenera kodiċi JIT. Meta metodu jissejjaħ għall-ewwel darba, jiġi kkompilat (u, iva, dan il-proċess mhuwiex mgħaġġel); fuq sejħiet sussegwenti, il-kontroll jiġi trasferit għall-metodu diġà kkompilat, u ma jkun hemm l-ebda tnaqqis sinifikanti fil-prestazzjoni.

Fil-każ tagħna, tista 'wkoll tuża l-kumpilazzjoni JIT u mbagħad tuża l-imġieba kkumpilata bl-istess prestazzjoni bħall-kontropartijiet AOT tagħha. L-espressjonijiet se jiġu għall-għajnuna tagħna f'dan il-każ.

Il-prinċipju inkwistjoni jista’ jiġi fformulat fil-qosor kif ġej:
Għandek tiġbor fil-cache r-riżultat finali tar-riflessjoni bħala delegat li fih il-funzjoni kkumpilata. Jagħmel sens ukoll li l-oġġetti kollha meħtieġa fil-cache bl-informazzjoni tat-tip fl-oqsma tat-tip tiegħek, il-ħaddiem, li huma maħżuna barra l-oġġetti.

Hemm loġika f'dan. Is-sens komun jgħidilna li jekk xi ħaġa tista 'tiġi kkumpilata u miżmumin fil-cache, allura għandu jsir.

B'ħarsa 'l quddiem, għandu jingħad li l-cache fil-ħidma bir-riflessjoni għandha l-vantaġġi tagħha, anki jekk ma tużax il-metodu propost ta' kumpilazzjoni ta 'espressjonijiet. Fil-fatt, hawnhekk qed sempliċement nirrepeti t-teżijiet tal-awtur tal-artiklu li għalih nirreferi hawn fuq.

Issa dwar il-kodiċi. Ejja nħarsu lejn eżempju li huwa bbażat fuq l-uġigħ riċenti tiegħi li kelli niffaċċja fi produzzjoni serja ta' istituzzjoni ta' kreditu serja. L-entitajiet kollha huma fittizji biex ħadd ma jaħtaf.

Hemm xi essenza. Ħalli jkun hemm Kuntatt. Hemm ittri b'korp standardizzat, li minnhom il-parser u l-idratatur joħolqu dawn l-istess kuntatti. Waslet ittra, qrajnieha, parsajniha f'pari ewlenin-valur, ħloqna kuntatt, u ssejvjaha fid-database.

Huwa elementari. Ejja ngħidu li kuntatt għandu l-proprjetajiet Isem sħiħ, Età u Telefon ta' Kuntatt. Din id-dejta tiġi trażmessa fl-ittra. In-negozju jrid ukoll appoġġ biex ikun jista 'jżid malajr ċwievet ġodda għall-immappjar tal-proprjetajiet tal-entità f'pari fil-korp tal-ittra. F'każ li xi ħadd għamel typo fil-mudell jew jekk qabel ir-rilaxx ikun meħtieġ li tniedi b'mod urġenti l-immappjar minn sieħeb ġdid, li jadatta għall-format il-ġdid. Imbagħad nistgħu nżidu korrelazzjoni ta 'mapping ġdida bħala datafix irħis. Jiġifieri eżempju tal-ħajja.

Aħna nimplimentaw, noħolqu testijiet. Xogħlijiet.

Mhux se nipprovdi l-kodiċi: hemm ħafna sorsi, u huma disponibbli fuq GitHub permezz tal-link fl-aħħar tal-artiklu. Tista 'tgħabbihom, ittorturahom mingħajr rikonoxximent u tkejjelhom, kif dan jaffettwa fil-każ tiegħek. Se nagħti biss il-kodiċi ta 'żewġ metodi ta' mudell li jiddistingwu l-hydrator, li suppost kellu jkun mgħaġġel, mill-hydrator, li suppost kien bil-mod.

Il-loġika hija kif ġej: il-metodu tal-mudell jirċievi pari ġġenerati mil-loġika bażika tal-parser. Is-saff LINQ huwa l-parser u l-loġika bażika tal-hydrator, li jagħmel talba lill-kuntest tad-database u jqabbel ċwievet ma 'pari mill-parser (għal dawn il-funzjonijiet hemm kodiċi mingħajr LINQ għal tqabbil). Sussegwentement, il-pari jgħaddu għall-metodu ta 'idratazzjoni prinċipali u l-valuri tal-pari huma ssettjati għall-proprjetajiet korrispondenti tal-entità.

"Mgħaġġel" (Prefiss Fast fil-parametri referenzjarji):

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

Kif nistgħu naraw, tintuża kollezzjoni statika bi proprjetajiet setter - lambdas ikkumpilati li jsejħu l-entità tas-setter. Maħluq mill-kodiċi li ġej:

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

B'mod ġenerali huwa ċar. Aħna jaqsmu l-proprjetajiet, noħolqu delegati għalihom li jsejħu s-setters, u nsalvawhom. Imbagħad inċemplu meta jkun meħtieġ.

“Slow” (Prefiss Slow fil-parametri referenzjarji):

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

Hawnhekk aħna immedjatament bypass il-proprjetajiet u sejħa SetValue direttament.

Għaċ-ċarezza u bħala referenza, implimentajt metodu naive li jikteb il-valuri tal-pari ta 'korrelazzjoni tagħhom direttament fl-oqsma tal-entità. Prefiss – Manwal.

Issa ejja nieħdu BenchmarkDotNet u neżaminaw il-prestazzjoni. U f'daqqa waħda... (spoiler - dan mhux ir-riżultat korrett, id-dettalji huma hawn taħt)

Artiklu bla suċċess dwar l-aċċellerazzjoni tar-riflessjoni

X'naraw hawn? Metodi li trijonfanti jġorru l-prefiss Fast jirriżultaw li huma aktar bil-mod fi kważi l-passes kollha minn metodi bil-prefiss Slow. Dan jgħodd kemm għall-allokazzjoni kif ukoll għall-ħeffa tax-xogħol. Min-naħa l-oħra, implimentazzjoni sabiħa u eleganti ta 'mapping bl-użu ta' metodi LINQ maħsuba għal dan kull fejn ikun possibbli, għall-kuntrarju, tnaqqas ħafna l-produttività. Id-differenza hija ta 'ordni. It-tendenza ma tinbidilx b'numri differenti ta 'passes. L-unika differenza hija fl-iskala. Bil-LINQ huwa 4 - 200 darba aktar bil-mod, hemm aktar żibel bejn wieħed u ieħor fuq l-istess skala.

UPDATED

Ma kontx nemmen li għajnejja, imma aktar importanti minn hekk, il-kollega tagħna la emmint l-għajnejn tiegħi u lanqas il-kodiċi tiegħi - Dmitry Tikhonov 0x1000000. Wara li ċċekkja doppjament is-soluzzjoni tiegħi, huwa skopra u rrimarka b'mod brillanti żball li tlift minħabba numru ta 'bidliet fl-implimentazzjoni, mill-bidu sa l-aħħar. Wara li rranġat il-bug misjub fis-setup Moq, ir-riżultati kollha waqgħu f'posthom. Skont ir-riżultati tat-test mill-ġdid, it-tendenza ewlenija ma tinbidilx - LINQ xorta taffettwa l-prestazzjoni aktar milli riflessjoni. Madankollu, huwa sabiħ li x-xogħol bil-kumpilazzjoni tal-Espressjoni ma jsirx għalxejn, u r-riżultat huwa viżibbli kemm fil-ħin tal-allokazzjoni kif ukoll tal-eżekuzzjoni. L-ewwel tnedija, meta l-oqsma statiċi huma inizjalizzati, hija naturalment aktar bil-mod għall-metodu "veloċi", iżda mbagħad is-sitwazzjoni tinbidel.

Hawn hu r-riżultat tat-test mill-ġdid:

Artiklu bla suċċess dwar l-aċċellerazzjoni tar-riflessjoni

Konklużjoni: meta tuża r-riflessjoni f'intrapriża, m'hemmx bżonn partikolari li tirrikorri għal tricks - LINQ se jiekol aktar il-produttività. Madankollu, f'metodi ta 'tagħbija għolja li jeħtieġu ottimizzazzjoni, tista' tiffranka riflessjoni fil-forma ta 'initilizzaturi u kompilaturi delegati, li mbagħad jipprovdu loġika "mgħaġġla". Dan il-mod tista 'żżomm kemm il-flessibbiltà tar-riflessjoni kif ukoll il-veloċità tal-applikazzjoni.

Il-kodiċi tal-benchmark huwa disponibbli hawn. Kulħadd jista' jiċċekkja darbtejn kliemi:
HabraReflectionTests

PS: il-kodiċi fit-testijiet juża IoC, u fil-benchmarks juża kostruzzjoni espliċita. Il-fatt hu li fl-implimentazzjoni finali nqata’ l-fatturi kollha li jistgħu jaffettwaw il-prestazzjoni u jagħmlu r-riżultat storbjuż.

PPS: Grazzi lill-utent Dmitry Tikhonov @0x1000000 talli skoprejt l-iżball tiegħi fit-twaqqif ta 'Moq, li affettwa l-ewwel kejl. Jekk xi wieħed mill-qarrejja għandu karma biżżejjed, jekk jogħġbok bħalha. Ir-raġel waqaf, ir-raġel qara, ir-raġel iċċekkja darbtejn u rrimarka l-iżball. Naħseb li dan jistħoqqlu rispett u simpatija.

PPPS: grazzi għall-qarrej metikoluż li wasal fil-qiegħ tal-istil u d-disinn. Jien għall-uniformità u l-konvenjenza. Id-diplomazija tal-preżentazzjoni tħalli ħafna x’tifhem, imma ħadt kont tal-kritika. Nitlob għall-projettili.

Sors: www.habr.com

Żid kumment