Makala ambayo hayajafaulu kuhusu kuharakisha kutafakari

Mara moja nitaelezea kichwa cha makala. Mpango wa awali ulikuwa ni kutoa ushauri mzuri na wa kutegemewa juu ya jinsi ya kuharakisha utumiaji wa kutafakari kwa kutumia mfano rahisi lakini wa kweli, lakini wakati wa kuweka alama ilibainika kuwa kutafakari sio polepole kama nilivyofikiria, LINQ ni polepole kuliko katika ndoto zangu za kutisha. Lakini mwishowe ikawa kwamba mimi pia nilifanya makosa katika vipimo ... Maelezo ya hadithi hii ya maisha ni chini ya kukata na katika maoni. Kwa kuwa mfano huo ni wa kawaida na unatekelezwa kwa kanuni kama kawaida hufanyika katika biashara, iligeuka kuwa ya kufurahisha sana, kama inavyoonekana kwangu, maonyesho ya maisha: athari kwa kasi ya mada kuu ya kifungu hicho ilikuwa. haionekani kwa sababu ya mantiki ya nje: Moq, Autofac, EF Core na wengine "kamba".

Nilianza kufanya kazi chini ya hisia ya nakala hii: Kwa nini Tafakari ni polepole

Kama unavyoona, mwandishi anapendekeza kutumia wajumbe waliokusanywa badala ya kupiga simu moja kwa moja njia za aina ya tafakari kama njia nzuri ya kuharakisha programu. Kuna, kwa kweli, utoaji wa IL, lakini ningependa kuizuia, kwani hii ndio njia inayohitaji nguvu ya kufanya kazi hiyo, ambayo imejaa makosa.

Kwa kuzingatia kwamba daima nimekuwa na maoni sawa kuhusu kasi ya kutafakari, sikukusudia hasa kuhoji hitimisho la mwandishi.

Mara nyingi mimi hukutana na matumizi ya ujinga ya kutafakari katika biashara. Aina inachukuliwa. Taarifa kuhusu mali inachukuliwa. Njia ya SetValue inaitwa na kila mtu anafurahi. Thamani imefika kwenye uwanja unaolengwa, kila mtu anafurahi. Watu wenye akili sana - wazee na viongozi wa timu - andika viendelezi vyao kupinga, kwa msingi wa utekelezaji wa ujinga wa "ulimwengu" wa aina moja hadi nyingine. Kiini kawaida ni hiki: tunachukua sehemu zote, kuchukua mali zote, kurudia juu yao: ikiwa majina ya washiriki wa aina yanalingana, tunatekeleza SetValue. Mara kwa mara tunapata ubaguzi kutokana na makosa ambapo hatukupata mali fulani katika aina moja, lakini hata hapa kuna njia ya nje ambayo inaboresha utendaji. Jaribu/kamata.

Nimeona watu wakibuni upya vichanganuzi na wachora ramani bila kuwa na taarifa kamili kuhusu jinsi mashine zilizokuja kabla yao zinavyofanya kazi. Nimeona watu wakificha utekelezaji wao wa ujinga nyuma ya mikakati, nyuma ya miingiliano, nyuma ya sindano, kana kwamba hii inaweza kutoa udhuru kwa bacchanalia inayofuata. Niliinua pua yangu juu kwa utambuzi kama huo. Kwa kweli, sikupima uvujaji halisi wa utendakazi, na, ikiwezekana, nilibadilisha tu utekelezaji kuwa "bora" zaidi ikiwa ningeweza kupata mikono yangu juu yake. Kwa hivyo, vipimo vya kwanza vilivyojadiliwa hapa chini vilinichanganya sana.

Nadhani wengi wenu, mkisoma Richter au wanaitikadi wengine, mmekutana na taarifa ya haki kabisa kwamba kuakisi katika msimbo ni jambo ambalo lina athari mbaya sana katika utendakazi wa programu.

Tafakari ya kupiga simu huilazimisha CLR kupitia mikusanyiko ili kupata ile wanayohitaji, kuvuta metadata zao, kuzichanganua, n.k. Kwa kuongeza, kutafakari wakati wa kupitisha mlolongo husababisha ugawaji wa kiasi kikubwa cha kumbukumbu. Tunatumia kumbukumbu, CLR inafichua GC na friezes huanza. Inapaswa kuwa polepole sana, niamini. Kiasi kikubwa cha kumbukumbu kwenye seva za kisasa za uzalishaji au mashine za wingu hazizuii ucheleweshaji mkubwa wa usindikaji. Kwa kweli, kadiri kumbukumbu inavyoongezeka, ndivyo uwezekano wako wa KUTAMBUA jinsi GC inavyofanya kazi. Tafakari ni, kwa nadharia, tambara nyekundu ya ziada kwake.

Hata hivyo, sisi sote tunatumia vyombo vya IoC na ramani za tarehe, kanuni ya uendeshaji ambayo pia inategemea kutafakari, lakini kwa kawaida hakuna maswali kuhusu utendaji wao. Hapana, si kwa sababu utangulizi wa utegemezi na uondoaji kutoka kwa miundo ya miktadha yenye mipaka ya nje ni muhimu sana hivi kwamba inatulazimu kudhabihu utendakazi kwa hali yoyote. Kila kitu ni rahisi - haiathiri sana utendaji.

Ukweli ni kwamba mifumo ya kawaida ambayo inategemea teknolojia ya kutafakari hutumia kila aina ya hila kufanya kazi nayo kikamilifu zaidi. Kawaida hii ni kashe. Kwa kawaida haya ni Maneno na wajumbe yaliyokusanywa kutoka kwa mti wa kujieleza. Kipanga otomatiki sawa hudumisha kamusi shindani inayolingana na aina zilizo na chaguo za kukokotoa ambazo zinaweza kubadilisha moja hadi nyingine bila kuita uakisi.

Je, hili linafikiwaje? Kimsingi, hii sio tofauti na mantiki ambayo jukwaa lenyewe hutumia kutoa msimbo wa JIT. Njia inapoitwa kwa mara ya kwanza, inakusanywa (na, ndio, mchakato huu sio haraka); kwa simu zinazofuata, udhibiti huhamishiwa kwa njia iliyokusanywa tayari, na hakutakuwa na athari kubwa za utendaji.

Kwa upande wetu, unaweza pia kutumia mkusanyiko wa JIT na kisha utumie tabia iliyokusanywa na utendaji sawa na wenzao wa AOT. Maneno yatatusaidia katika kesi hii.

Kanuni inayohusika inaweza kutengenezwa kwa ufupi kama ifuatavyo:
Unapaswa kuweka akiba matokeo ya mwisho ya kuakisi kama mjumbe aliye na kazi iliyokusanywa. Inaeleweka pia kuweka akiba ya vitu vyote muhimu na habari ya aina kwenye uwanja wa aina yako, mfanyakazi, ambayo imehifadhiwa nje ya vitu.

Kuna mantiki katika hili. Akili ya kawaida inatuambia kwamba ikiwa kitu kinaweza kukusanywa na kuhifadhiwa, basi kinapaswa kufanywa.

Kuangalia mbele, inapaswa kuwa alisema kuwa cache katika kufanya kazi na kutafakari ina faida zake, hata ikiwa hutumii njia iliyopendekezwa ya kukusanya maneno. Kwa kweli, hapa ninarudia tu nadharia za mwandishi wa kifungu ambacho ninarejelea hapo juu.

Sasa kuhusu kanuni. Hebu tuangalie mfano ambao unatokana na maumivu yangu ya hivi majuzi ambayo nilipaswa kukabiliana nayo katika uzalishaji mkubwa wa taasisi kubwa ya mikopo. Vyombo vyote ni vya uwongo ili mtu yeyote asikisie.

Kuna kiini fulani. Wacha tuwe na Mawasiliano. Kuna barua zilizo na mwili sanifu, ambayo kichanganuzi na hydrator huunda anwani hizi sawa. Barua ilifika, tukaisoma, tukaichanganua katika jozi za thamani-msingi, tukaunda anwani, na kuihifadhi kwenye hifadhidata.

Ni ya msingi. Hebu tuseme mwasiliani ana sifa ya Jina Kamili, Umri na Simu ya Mawasiliano. Data hii inapitishwa katika barua. Biashara pia inataka usaidizi wa kuweza kuongeza kwa haraka funguo mpya za kuchora sifa za huluki katika jozi katika sehemu ya herufi. Iwapo mtu alikosea katika kiolezo au ikiwa kabla ya kutolewa ni muhimu kuzindua kwa haraka ramani kutoka kwa mshirika mpya, kulingana na umbizo jipya. Kisha tunaweza kuongeza uunganisho mpya wa ramani kama datafix ya bei nafuu. Hiyo ni, mfano wa maisha.

Tunatekeleza, tengeneza vipimo. Inafanya kazi.

Sitatoa nambari: kuna vyanzo vingi, na vinapatikana kwenye GitHub kupitia kiunga mwishoni mwa kifungu. Unaweza kuzipakia, kuzitesa kupita kutambulika na kuzipima, kama ingeathiri katika kesi yako. Nitatoa tu msimbo wa njia mbili za template ambazo zinafautisha hydrator, ambayo ilipaswa kuwa haraka, kutoka kwa hydrator, ambayo ilipaswa kuwa polepole.

Mantiki ni kama ifuatavyo: njia ya kiolezo hupokea jozi zinazozalishwa na mantiki ya msingi ya kichanganuzi. Safu ya LINQ ni kichanganuzi na mantiki ya msingi ya hidrata, ambayo hufanya ombi kwa muktadha wa hifadhidata na kulinganisha funguo na jozi kutoka kwa kichanganuzi (kwa kazi hizi kuna msimbo bila LINQ kwa kulinganisha). Ifuatayo, jozi hupitishwa kwa njia kuu ya unyevu na maadili ya jozi huwekwa kwa mali inayolingana ya chombo.

"Haraka" (Kiambishi awali Haraka katika vigezo):

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

Kama tunavyoona, mkusanyiko tuli na sifa za seti hutumiwa - lambdas zilizokusanywa ambazo huita chombo cha seti. Imeundwa kwa nambari ifuatayo:

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

Kwa ujumla ni wazi. Tunapitia mali, kuunda wajumbe kwa ajili yao wanaoita seti, na kuwahifadhi. Kisha tunaita inapobidi.

β€œPolepole” (Kiambishi awali Polepole katika viwango):

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

Hapa tunapita mara moja mali na kupiga simu SetValue moja kwa moja.

Kwa uwazi na kama rejeleo, nilitekelezea njia isiyo na maana ambayo huandika maadili ya jozi zao za uunganisho moja kwa moja kwenye sehemu za huluki. Kiambishi awali - Mwongozo.

Sasa hebu tuchukue BenchmarkDotNet na tuchunguze utendaji. Na ghafla ... (spoiler - hii sio matokeo sahihi, maelezo ni chini)

Makala ambayo hayajafaulu kuhusu kuharakisha kutafakari

Tunaona nini hapa? Mbinu ambazo hubeba kiambishi awali cha Haraka kwa ushindi hugeuka kuwa polepole katika takriban kupita zote kuliko mbinu zilizo na kiambishi awali cha Polepole. Hii ni kweli kwa ugawaji na kasi ya kazi. Kwa upande mwingine, utekelezaji mzuri na wa kifahari wa uchoraji wa ramani kwa kutumia njia za LINQ zilizokusudiwa kwa hili popote iwezekanavyo, kinyume chake, hupunguza sana tija. Tofauti ni ya utaratibu. Mwenendo haubadiliki na idadi tofauti ya kupita. Tofauti pekee ni katika kiwango. Kwa LINQ ni polepole mara 4 - 200, kuna takataka nyingi kwa takriban kiwango sawa.

Updated

Sikuamini macho yangu, lakini muhimu zaidi, mwenzetu hakuamini macho yangu au kanuni yangu - Dmitry Tikhonov 0x1000000. Baada ya kukagua suluhisho langu mara mbili, aligundua kwa busara na akaonyesha kosa ambalo nilikosa kwa sababu ya mabadiliko kadhaa katika utekelezaji, ya awali hadi ya mwisho. Baada ya kurekebisha hitilafu iliyopatikana katika usanidi wa Moq, matokeo yote yalianguka mahali. Kulingana na matokeo ya majaribio, mwelekeo kuu haubadilika - LINQ bado huathiri utendaji zaidi kuliko kutafakari. Hata hivyo, ni vizuri kwamba kazi na mkusanyiko wa Expression haifanyiki bure, na matokeo yanaonekana katika ugawaji na wakati wa utekelezaji. Uzinduzi wa kwanza, wakati mashamba ya tuli yameanzishwa, kwa kawaida ni polepole kwa njia ya "haraka", lakini basi hali inabadilika.

Hapa kuna matokeo ya jaribio tena:

Makala ambayo hayajafaulu kuhusu kuharakisha kutafakari

Hitimisho: unapotumia tafakari katika biashara, hakuna haja maalum ya kuamua hila - LINQ itakula tija zaidi. Walakini, kwa njia za upakiaji wa juu ambazo zinahitaji uboreshaji, unaweza kuhifadhi tafakari kwa njia ya waanzishaji na wakusanyaji wa wajumbe, ambayo itatoa mantiki ya "haraka". Kwa njia hii unaweza kudumisha unyumbufu wa kutafakari na kasi ya programu.

Nambari ya alama inapatikana hapa. Mtu yeyote anaweza kuangalia maneno yangu mara mbili:
Majaribio ya HabraReflection

PS: nambari kwenye majaribio hutumia IoC, na kwenye alama hutumia muundo wazi. Ukweli ni kwamba katika utekelezaji wa mwisho nilikata mambo yote ambayo yanaweza kuathiri utendaji na kufanya matokeo kuwa kelele.

PPS: Shukrani kwa mtumiaji Dmitry Tikhonov @0x1000000 kwa kugundua kosa langu katika kusanidi Moq, ambayo iliathiri vipimo vya kwanza. Ikiwa msomaji yeyote ana karma ya kutosha, tafadhali ipende. Yule mtu akasimama, yule mtu akasoma, yule mtu akaangalia mara mbili na kuashiria kosa. Nadhani hii inastahili heshima na huruma.

PPPS: shukrani kwa msomaji makini ambaye alifikia mwisho wa mtindo na muundo. Mimi ni kwa ajili ya usawa na urahisi. Diplomasia ya uwasilishaji inaacha kuhitajika, lakini nilizingatia ukosoaji huo. naomba projectile.

Chanzo: mapenzi.com

Kuongeza maoni