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:
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)
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 -
Hawn hu r-riżultat tat-test mill-ġdid:
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:
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
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