Es tÅ«lÄ«t paskaidroÅ”u raksta nosaukumu. SÄkotnÄjais plÄns bija sniegt labus, uzticamus padomus, kÄ paÄtrinÄt refleksijas izmantoÅ”anu, izmantojot vienkÄrÅ”u, bet reÄlistisku piemÄru, taÄu benchmarkinga laikÄ izrÄdÄ«jÄs, ka refleksija nav tik lÄna, kÄ domÄju, LINQ ir lÄnÄks nekÄ manos murgos. Bet beigÄs izrÄdÄ«jÄs, ka arÄ« es kļūdÄ«jos mÄrÄ«jumos... SÄ«kÄka informÄcija par Å”o dzÄ«vesstÄstu ir zem griezuma un komentÄros. TÄ kÄ piemÄrs ir diezgan ikdieniŔķs un principÄ Ä«stenots, kÄ tas parasti tiek darÄ«ts uzÅÄmumÄ, tas izrÄdÄ«jÄs diezgan interesants, kÄ man Ŕķiet, dzÄ«ves paraugdemonstrÄjums: ietekme uz raksta galvenÄs tÄmas Ätrumu bija nav manÄms ÄrÄjÄs loÄ£ikas dÄļ: Moq, Autofac, EF Core un citi "joslas".
Es sÄku strÄdÄt pÄc Ŕī raksta iespaida:
KÄ redzat, autors iesaka izmantot apkopotus delegÄtus, nevis tieÅ”i izsaukt refleksijas tipa metodes, jo tas ir lielisks veids, kÄ ievÄrojami paÄtrinÄt lietojumprogrammu. Protams, ir IL emisija, bet es gribÄtu no tÄs izvairÄ«ties, jo tas ir darbietilpÄ«gÄkais veids, kÄ veikt uzdevumu, kurÄ ir daudz kļūdu.
Å emot vÄrÄ to, ka man vienmÄr ir bijis lÄ«dzÄ«gs viedoklis par refleksijas Ätrumu, es Ä«paÅ”i nedomÄju apÅ”aubÄ«t autora secinÄjumus.
UzÅÄmumÄ bieži sastopos ar naivu refleksijas izmantoÅ”anu. Veids ir uzÅemts. Tiek Åemta informÄcija par Ä«paÅ”umu. Tiek izsaukta SetValue metode un visi priecÄjas. VÄrtÄ«ba ir nonÄkusi mÄrÄ·a laukÄ, visi ir apmierinÄti. Ä»oti gudri cilvÄki - seniori un komandas vadÄ«tÄji - raksta savus paplaÅ”inÄjumus objektam, balstoties uz tik naivu realizÄciju, viena veida "universÄlie" kartÄtÄji uz otru. BÅ«tÄ«ba parasti ir Å”Äda: mÄs Åemam visus laukus, Åemam visus rekvizÄ«tus, atkÄrtojam tos: ja tipa dalÄ«bnieku nosaukumi sakrÄ«t, mÄs izpildÄm SetValue. Ik pa laikam pieÄ·eram izÅÄmumus kļūdu dÄļ, kur neatradÄm kÄdu Ä«paÅ”umu kÄdÄ no veidiem, taÄu arÄ« Å”eit ir izeja, kas uzlabo veiktspÄju. IzmÄÄ£ini/noÄ·er.
Esmu redzÄjis, ka cilvÄki no jauna izgudro parsÄtÄjus un kartÄtÄjus, nebÅ«dami pilnÄ«bÄ bruÅoti ar informÄciju par to, kÄ darbojas pirms viÅiem esoÅ”Äs maŔīnas. Esmu redzÄjis, ka cilvÄki slÄpj savas naivÄs ievieÅ”anas aiz stratÄÄ£ijÄm, aiz saskarnÄm, aiz injekcijÄm, it kÄ tas attaisnotu turpmÄko bakhanÄliju. Es pagriezu degunu uz Å”Ädu atziÅu. PatiesÄ«bÄ es nenovÄrtÄju reÄlo veiktspÄjas noplÅ«di un, ja iespÄjams, es vienkÄrÅ”i mainÄ«ju ievieÅ”anu uz āoptimÄlÄkuā, ja varÄju to iegÅ«t. TÄpÄc pirmie zemÄk aplÅ«kotie mÄrÄ«jumi mani nopietni mulsinÄja.
Es domÄju, ka daudzi no jums, lasot Rihteru vai citus ideologus, ir saskÄruÅ”ies ar pilnÄ«gi godÄ«gu apgalvojumu, ka atspoguļojums kodÄ ir parÄdÄ«ba, kas ÄrkÄrtÄ«gi negatÄ«vi ietekmÄ lietojumprogrammas darbÄ«bu.
Refleksijas izsaukÅ”ana liek CLR iziet cauri komplektiem, lai atrastu vajadzÄ«go, izvilktu metadatus, parsÄtu tos utt. TurklÄt pÄrdomas, ŔķÄrsojot secÄ«bas, noved pie liela apjoma atmiÅas pieŔķirÅ”anas. MÄs izmantojam atmiÅu, CLR atklÄj GC un sÄkas frÄ«zes. Tam vajadzÄtu bÅ«t manÄmi lÄnam, ticiet man. Lielais atmiÅas apjoms mÅ«sdienu ražoÅ”anas serveros vai mÄkoÅa iekÄrtÄs nenovÄrÅ” lielu apstrÄdes aizkavi. PatiesÄ«bÄ, jo vairÄk atmiÅas, jo lielÄka iespÄja, ka PEVÄRÄSIT, kÄ darbojas GC. TeorÄtiski refleksija viÅam ir Ä«paÅ”i sarkana lupata.
TaÄu mÄs visi lietojam IoC konteinerus un datuma kartÄtÄjus, kuru darbÄ«bas princips arÄ« balstÄs uz refleksiju, taÄu par to veiktspÄju parasti nerodas jautÄjumi. NÄ, ne tÄpÄc, ka atkarÄ«bu ievieÅ”ana un abstrakcija no ÄrÄjiem ierobežota konteksta modeļiem ir tik nepiecieÅ”ama, ka mums jebkurÄ gadÄ«jumÄ ir jÄupurÄ veiktspÄja. Viss ir vienkÄrÅ”Äk - tas patieÅ”Äm neietekmÄ veiktspÄju.
Fakts ir tÄds, ka visizplatÄ«tÄkie ietvari, kas ir balstÄ«ti uz refleksijas tehnoloÄ£iju, izmanto visu veidu trikus, lai ar to strÄdÄtu optimÄlÄk. Parasti Ŕī ir keÅ”atmiÅa. Parasti tÄs ir izteiksmes un delegÄti, kas apkopoti no izteiksmju koka. Tas pats automapper uztur konkurÄtspÄjÄ«gu vÄrdnÄ«cu, kas saskaÅo veidus ar funkcijÄm, kuras var pÄrvÄrst vienu citÄ, neizsaucot refleksiju.
KÄ tas tiek panÄkts? BÅ«tÄ«bÄ tas neatŔķiras no loÄ£ikas, ko pati platforma izmanto JIT koda Ä£enerÄÅ”anai. Kad metode tiek izsaukta pirmo reizi, tÄ tiek kompilÄta (un, jÄ, Å”is process nav Ätrs); nÄkamajos izsaukumos kontrole tiek pÄrnesta uz jau kompilÄto metodi, un nebÅ«s bÅ«tisku veiktspÄjas kritumu.
MÅ«su gadÄ«jumÄ varat izmantot arÄ« JIT kompilÄciju un pÄc tam izmantot kompilÄto darbÄ«bu ar tÄdu paÅ”u veiktspÄju kÄ tÄs AOT kolÄÄ£iem. Å ajÄ gadÄ«jumÄ mums palÄ«dzÄs izteicieni.
AttiecÄ«go principu var Ä«si formulÄt Å”Ädi:
PÄrdomu gala rezultÄts ir jÄsaglabÄ keÅ”atmiÅÄ kÄ delegÄtam, kas satur apkopoto funkciju. Ir arÄ« jÄga keÅ”atmiÅÄ saglabÄt visus nepiecieÅ”amos objektus ar tipa informÄciju jÅ«su tipa, darbinieka laukos, kas tiek glabÄti Ärpus objektiem.
Å eit ir loÄ£ika. Veselais saprÄts mums saka, ka, ja kaut ko var apkopot un saglabÄt keÅ”atmiÅÄ, tad tas ir jÄdara.
Raugoties nÄkotnÄ, jÄsaka, ka keÅ”atmiÅai darbÄ ar refleksiju ir savas priekÅ”rocÄ«bas, pat ja jÅ«s neizmantojat piedÄvÄto izteiksmju apkopoÅ”anas metodi. PatiesÄ«bÄ Å”eit es vienkÄrÅ”i atkÄrtoju raksta autora tÄzes, uz kurÄm atsaucos iepriekÅ”.
Tagad par kodu. ApskatÄ«sim piemÄru, kas balstÄ«ts uz manÄm nesenajÄm sÄpÄm, ar kurÄm man nÄcÄs saskarties nopietnas kredÄ«tiestÄdes nopietnÄ iestudÄjumÄ. Visas vienÄ«bas ir fiktÄ«vas, lai neviens to neuzminÄtu.
Ir kaut kÄda bÅ«tÄ«ba. Lai ir Kontakts. Ir burti ar standartizÄtu korpusu, no kuriem analizÄtÄjs un mitrinÄtÄjs izveido tos paÅ”us kontaktus. AtnÄca vÄstule, mÄs to izlasÄ«jÄm, parsÄjÄm atslÄgu un vÄrtÄ«bu pÄros, izveidojÄm kontaktpersonu un saglabÄjÄm datu bÄzÄ.
Tas ir elementÄri. PieÅemsim, ka kontaktpersonai ir rekvizÄ«ti Pilns vÄrds, vecums un KontakttÄlrunis. Å ie dati tiek pÄrsÅ«tÄ«ti vÄstulÄ. UzÅÄmums arÄ« vÄlas saÅemt atbalstu, lai vÄstules pamattekstÄ varÄtu Ätri pievienot jaunas atslÄgas entÄ«tijas rekvizÄ«tu kartÄÅ”anai pa pÄriem. GadÄ«jumÄ, ja kÄds veidnÄ ir pieļÄvis drukas kļūdu vai ja pirms izlaiÅ”anas ir nepiecieÅ”ams steidzami palaist kartÄÅ”anu no jauna partnera, pielÄgojoties jaunajam formÄtam. PÄc tam mÄs varam pievienot jaunu kartÄÅ”anas korelÄciju kÄ lÄtu datu labojumu. Tas ir, dzÄ«ves piemÄrs.
IevieŔam, veidojam testus. Darbojas.
Es nesniegÅ”u kodu: ir daudz avotu, un tie ir pieejami vietnÄ GitHub, izmantojot saiti raksta beigÄs. JÅ«s varat tos ielÄdÄt, spÄ«dzinÄt lÄ«dz nepazÄ«Å”anai un izmÄrÄ«t, kÄ tas ietekmÄtu jÅ«su gadÄ«jumu. Es doÅ”u tikai divu veidÅu metožu kodu, kas atŔķir mitrinÄtÄju, kuram vajadzÄja bÅ«t Ätram, no mitrinÄtÄja, kuram vajadzÄja bÅ«t lÄnam.
LoÄ£ika ir Å”Äda: veidnes metode saÅem pÄrus, ko Ä£enerÄ pamata parsÄtÄja loÄ£ika. LINQ slÄnis ir parsÄtÄjs un hidratora pamata loÄ£ika, kas veic pieprasÄ«jumu datu bÄzes kontekstam un salÄ«dzina atslÄgas ar parsÄtÄja pÄriem (Ŕīm funkcijÄm salÄ«dzinÄÅ”anai ir kods bez LINQ). PÄc tam pÄri tiek nodoti galvenajai hidratÄcijas metodei, un pÄru vÄrtÄ«bas tiek iestatÄ«tas uz attiecÄ«gajÄm entÄ«tijas Ä«paŔībÄm.
āÄtrsā (etalonos prefikss Fast):
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;
}
KÄ redzam, tiek izmantota statiskÄ kolekcija ar settera Ä«paŔībÄm ā kompilÄtas lambdas, kas izsauc setera entÄ«tiju. Izveidots ar Å”Ädu kodu:
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();
}
KopumÄ ir skaidrs. MÄs ŔķÄrsojam rekvizÄ«tus, izveidojam tiem delegÄtus, kas izsauc iestatÄ«tÄjus, un saglabÄjam tos. Tad sazvanÄmies, kad nepiecieÅ”ams.
āLÄnsā (prefikss LÄns etalonos):
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;
}
Å eit mÄs nekavÄjoties apietam rekvizÄ«tus un tieÅ”i izsaucam SetValue.
SkaidrÄ«bas labad un kÄ atsauci es ieviesu naivu metodi, kas ieraksta to korelÄcijas pÄru vÄrtÄ«bas tieÅ”i entÄ«tiju laukos. Prefikss - rokasgrÄmata.
Tagad Åemsim BenchmarkDotNet un pÄrbaudÄ«sim veiktspÄju. Un pÄkÅ”Åi... (spoileris - tas nav pareizais rezultÄts, sÄ«kÄka informÄcija zemÄk)
Ko mÄs Å”eit redzam? Metodes, kas triumfÄ ar prefiksu Fast, gandrÄ«z visos piegÄjienos izrÄdÄs lÄnÄkas nekÄ metodes ar prefiksu LÄnÄ. Tas attiecas gan uz sadalÄ«jumu, gan uz darba Ätrumu. No otras puses, skaista un eleganta kartÄÅ”anas ievieÅ”ana, izmantojot Å”im nolÅ«kam paredzÄtÄs LINQ metodes, kur vien iespÄjams, gluži pretÄji, ievÄrojami samazina produktivitÄti. AtŔķirÄ«ba ir kÄrtÄ«bÄ. Tendence nemainÄs ar dažÄdu piespÄļu skaitu. VienÄ«gÄ atŔķirÄ«ba ir mÄrogÄ. Ar LINQ tas ir 4 - 200 reizes lÄnÄks, ir vairÄk atkritumu apmÄram tÄdÄ paÅ”Ä mÄrogÄ.
UPDATED
Es neticÄju savÄm acÄ«m, bet vÄl svarÄ«gÄk ir tas, ka mÅ«su kolÄÄ£is neticÄja ne manÄm acÄ«m, ne manam kodam -
Å eit ir atkÄrtotas pÄrbaudes rezultÄts:
SecinÄjums: izmantojot refleksiju uzÅÄmumÄ, nav Ä«paÅ”as vajadzÄ«bas Ä·erties pie trikiem - LINQ vairÄk apÄdÄ«s produktivitÄti. TomÄr augstas slodzes metodÄs, kurÄm nepiecieÅ”ama optimizÄcija, varat saglabÄt pÄrdomas inicializatoru un deleÄ£Äto kompilatoru veidÄ, kas pÄc tam nodroÅ”inÄs āÄtruā loÄ£iku. TÄdÄ veidÄ jÅ«s varat saglabÄt gan refleksijas elastÄ«bu, gan aplikÄcijas Ätrumu.
Etalona kods ir pieejams Å”eit. Ikviens var vÄlreiz pÄrbaudÄ«t manus vÄrdus:
PS: kods testos izmanto IoC, un etalonos tas izmanto skaidru konstrukciju. Fakts ir tÄds, ka galÄ«gajÄ ievieÅ”anÄ es nogriezu visus faktorus, kas varÄtu ietekmÄt veiktspÄju un padarÄ«t rezultÄtu trokÅ”Åainu.
PPS: Paldies lietotÄjam
PPPS: paldies rÅ«pÄ«gajam lasÄ«tÄjam, kurÅ” saprata stilu un dizainu. Esmu par vienveidÄ«bu un ÄrtÄ«bas. PrezentÄcijas diplomÄtija atstÄj daudz ko vÄlÄties, taÄu kritiku ÅÄmu vÄrÄ. Es lÅ«dzu Å”ÄviÅu.
Avots: www.habr.com