Мақолаи бемуваффақият дар бораи суръатбахшии инъикос

Ман фавран унвони мақоларо шарҳ медиҳам. Нақшаи аслӣ додани маслиҳати хуб ва боэътимод дар бораи суръат бахшидан ба истифодаи инъикос бо истифода аз як мисоли оддӣ, вале воқеӣ буд, аммо ҳангоми муқоиса маълум шуд, ки инъикос он қадар суст нест, ки ман фикр мекардам, LINQ нисбат ба хобҳои ман сусттар аст. Аммо дар охир маълум шуд, ки ман ҳам дар андозагирӣ хато кардаам... Ҷузъиёти ин достони зиндагӣ дар зери буриш ва дар шарҳҳост. Азбаски мисол хеле маъмул аст ва ба таври принципиалӣ, чунон ки одатан дар корхона иҷро карда мешавад, он хеле ҷолиб буд, ба назари ман, як намоиши ҳаёт буд: таъсир ба суръати мавзӯи асосии мақола буд. аз сабаби мантиқи беруна намоён нест: Moq, Autofac, EF Core ва дигарон "тасмаҳо".

Ман зери таассуроти ин мақола ба кор шурӯъ кардам: Чаро Мулоҳиза суст аст

Тавре ки шумо мебинед, муаллиф ба ҷои мустақиман даъват кардани усулҳои намуди инъикос истифода бурдани вакилони тартибдодашударо ҳамчун як роҳи олии суръатбахшии барнома пешниҳод мекунад. Албатта, партови IL вуҷуд дорад, аммо ман мехостам аз он канорагирӣ кунам, зеро ин роҳи аз ҳама заҳматталаби иҷрои вазифаест, ки бо хатогиҳо пур аст.

Бо дарназардошти он, ки ман ҳамеша дар бораи суръати инъикос ақидаи якхела доштам, ман махсусан ният надоштам, ки хулосаҳои муаллифро зери шубҳа гузорам.

Ман аксар вақт ба истифодаи соддалавҳона дар корхона дучор мешавам. Навъи гирифта мешавад. Маълумот дар бораи молу мулк гирифта мешавад. Усули SetValue номида мешавад ва ҳама шод мешаванд. Арзиш ба майдони ҳадаф расид, ҳама шоданд. Одамони хеле оқил - пиронсолон ва роҳбарони гурӯҳ - васеъшавии худро ба объект менависанд, ки дар асоси чунин амалисозии соддалавҳона харитасозони "универсалӣ" аз як намуди дигар ба дигараш. Моҳият одатан аз ин иборат аст: мо ҳама майдонҳоро мегирем, ҳамаи хосиятҳоро мегирем, дар болои онҳо такрор мекунем: агар номҳои аъзои намуд мувофиқат кунанд, мо SetValue -ро иҷро мекунем. Баъзан мо аз сабаби хатогиҳо истисноҳо ба даст меорем, ки дар яке аз намудҳо ягон амволро наёфтаем, аммо ҳатто дар ин ҷо роҳи баромад вуҷуд дорад, ки иҷрои онро беҳтар мекунад. Кӯшиш кунед / сайд кунед.

Ман дидаам, ки одамон парсерҳо ва харитасозҳоро аз нав ихтироъ мекунанд, бе он ки бо маълумот дар бораи чӣ гуна кор кардани мошинҳои пеш аз онҳо омада пурра муҷаҳҳаз бошанд. Ман дидаам, ки одамон татбиқи соддалавҳии худро дар паси стратегияҳо, паси интерфейсҳо, паси тазриқҳо пинҳон мекунанд, гӯё ин баканалии минбаъдаро баҳона мекунад. Ман аз чунин даркҳо бинӣ кардам. Дар асл, ман ихроҷи воқеии иҷроишро чен накардам ва агар имконпазир бошад, ман татбиқро ба "беҳтарин" иваз кардам, агар ман онро ба даст оварда метавонам. Аз ин рӯ, ченакҳои аввалине, ки дар поён муҳокима шудаанд, маро ба таври ҷиддӣ ошуфта карданд.

Ман фикр мекунам, ки бисёре аз шумо, ҳангоми хондани Рихтер ё идеологҳои дигар, бо изҳороти комилан одилона дучор омадаед, ки инъикос дар код як падидаест, ки ба иҷрои барнома таъсири бениҳоят манфӣ мерасонад.

Даъвати инъикос CLR-ро маҷбур мекунад, ки аз маҷлисҳо гузарад, то онеро, ки ба онҳо лозим аст, пайдо кунад, метадотаҳои онҳоро кашад, таҳлил кунад ва ғайра. Илова бар ин, инъикос ҳангоми гузариши пайдарпайҳо боиси тақсимоти миқдори зиёди хотира мегардад. Мо хотираро истифода мебарем, CLR GC-ро кашф мекунад ва фризҳо оғоз мешаванд. Он бояд ба таври назаррас суст бошад, ба ман бовар кунед. Миқдори зиёди хотира дар серверҳои истеҳсолии муосир ё мошинҳои абрӣ таъхирҳои баланди коркардро пешгирӣ намекунад. Дарвоқеъ, чӣ қадаре ки хотира зиёд бошад, ҳамон қадар эҳтимоли зиёд аст, ки шумо чӣ гуна кор кардани GC-ро ДОХИЛ кунед. Мулоҳиза барои ӯ дар назария як латтаи сурхи иловагӣ аст.

Бо вуҷуди ин, мо ҳама контейнерҳои IoC ва харитасозони санаро истифода мебарем, ки принсипи кори онҳо низ ба инъикос асос ёфтааст, аммо одатан дар бораи иҷрои онҳо саволҳо вуҷуд надоранд. Не, на аз он сабаб, ки ҷорӣ кардани вобастагӣ ва абстраксия аз моделҳои контекстии берунӣ он қадар зарур аст, ки мо бояд дар ҳама ҳолат иҷроишро қурбон кунем. Ҳама чиз соддатар аст - он воқеан ба иҷроиш чандон таъсир намерасонад.

Гап дар он аст, ки чаҳорчӯбаҳои маъмултарине, ки ба технологияи инъикос асос ёфтаанд, барои беҳтар кор кардан бо он ҳама гуна ҳилаҳоро истифода мебаранд. Одатан ин кэш аст. Одатан инҳо Ифодаҳо ва намояндаҳое мебошанд, ки аз дарахти ифода тартиб дода шудаанд. Худи ҳамон automapper луғати рақобатпазирро нигоҳ медорад, ки ба намудҳо бо функсияҳое мувофиқат мекунад, ки метавонанд бидуни даъвати инъикос якеро ба дигаре табдил диҳанд.

Ин чӣ гуна ба даст оварда шудааст? Аслан, ин аз мантиқе, ки худи платформа барои тавлиди рамзи JIT истифода мебарад, фарқ надорад. Вақте ки усул бори аввал даъват карда мешавад, он тартиб дода мешавад (ва, ҳа, ин раванд зуд нест); дар зангҳои минбаъда, назорат ба усули аллакай тартибдодашуда интиқол дода мешавад ва ҳеҷ гуна коҳиши назарраси иҷроиш вуҷуд нахоҳад дошт.

Дар ҳолати мо, шумо инчунин метавонед компилясияи JIT-ро истифода баред ва сипас рафтори тартибдодашударо бо ҳамон кор бо ҳамтоёни AOT истифода баред. Дар ин сурат ифодахо ба ёрии мо меоянд.

Принсипи мавриди назарро метавон ба таври мухтасар чунин ифода кард:
Шумо бояд натиҷаи ниҳоии инъикосро ҳамчун вакили дорои функсияи тартибдодашуда кэш кунед. Инчунин кэш кардани ҳама объектҳои зарурӣ бо маълумоти навъи дар майдонҳои навъи шумо, коргар, ки берун аз объектҳо нигоҳ дошта мешаванд, маъно дорад.

Дар ин мантиқ ҳаст. Ақли солим ба мо мегӯяд, ки агар чизеро тартиб додан ва кэш кардан мумкин аст, пас он бояд анҷом дода шавад.

Ба пеш нигоҳ карда, бояд гуфт, ки кэш дар кор бо инъикос бартариҳои худро дорад, ҳатто агар шумо усули пешниҳодшудаи тартиб додани ифодаҳоро истифода набаред. Воқеан, ман дар ин ҷо танҳо тезисҳои муаллифи мақоларо, ки дар боло ишора кардам, такрор мекунам.

Акнун дар бораи код. Биёед мисолеро бубинем, ки ба дарди охирини ман, ки ман дар як истеҳсолоти ҷиддии як ташкилоти қарзии ҷиддӣ рӯбарӯ шудам, асос ёфтааст. Ҳама объектҳо сохтаанд, то касе тахмин накунад.

Баъзе моҳият вуҷуд дорад. Бигзор тамос бошад. Ҳарфҳои дорои бадани стандартишуда мавҷуданд, ки аз онҳо таҳлилгар ва гидратор ин алоқаҳоро эҷод мекунанд. Мактуб омад, мо онро хондем, онро ба ҷуфтҳои калидӣ-арзиш таҳлил кардем, алоқа эҷод кардем ва онро дар базаи маълумот захира кардем.

Ин ибтидоӣ аст. Фарз мекунем, ки алоқа дорои хосиятҳои Номи пурра, синну сол ва телефони тамос мебошад. Ин маълумот дар мактуб интиқол дода мешавад. Бизнес инчунин мехоҳад, ки дастгирӣ барои зуд илова кардани калидҳои нав барои харитасозии хосиятҳои объект ба ҷуфтҳо дар матни мактуб. Агар касе дар қолаб хатои хаттӣ содир карда бошад ва ё пеш аз баровардан зарур бошад, ки ба таври фаврӣ харитасозӣ аз шарики нав, мутобиқ шудан ба формати навро оғоз кунад. Он гоҳ мо метавонем як коррелятсияи нави харитасозӣ ҳамчун маълумотҳои арзон илова кунем. Яъне як мисоли ҳаёт.

Мо амалӣ мекунем, озмоишҳо эҷод мекунем. Кор мекунад.

Ман рамзро пешниҳод намекунам: сарчашмаҳои зиёде мавҷуданд ва онҳо дар GitHub тавассути истиноди охири мақола дастрасанд. Шумо метавонед онҳоро бор кунед, онҳоро ба таври шинохтанашаванда шиканҷа кунед ва чен кунед, зеро ин ба ҳолати шумо таъсир мерасонад. Ман танҳо рамзи ду усули шаблонро медиҳам, ки гидроторро, ки бояд зуд бошад, аз гидроторе, ки бояд суст бошад, фарқ мекунад.

Мантиқ чунин аст: усули шаблон ҷуфтҳоеро, ки бо мантиқи асосии таҳлилгар тавлид шудаанд, қабул мекунад. Қабати LINQ таҳлилгар ва мантиқи асосии гидротор мебошад, ки ба контексти пойгоҳи додаҳо дархост пешниҳод мекунад ва калидҳоро бо ҷуфтҳои парсер муқоиса мекунад (барои ин функсияҳо код бе LINQ барои муқоиса мавҷуд аст). Баъдан, ҷуфтҳо ба усули асосии гидрататсия гузаронида мешаванд ва арзишҳои ҷуфтҳо ба хосиятҳои мувофиқи объект муқаррар карда мешаванд.

"Фаст" (Префикси 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;
        }

Тавре ки мо мебинем, коллексияи статикӣ бо хосиятҳои танзимкунанда истифода мешавад - ламбдаҳои тартибдодашуда, ки объекти танзимкунандаро даъват мекунанд. Бо коди зерин сохта шудааст:

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

Умуман равшан аст. Мо хосиятҳоро мегузарем, барои онҳо вакилоне эҷод мекунем, ки танзимкунандагонро даъват мекунанд ва онҳоро захира мекунем. Баъд дар мавриди зарурат занг мезанем.

"Саст" (Префикси суст дар нишондиҳандаҳо):

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

Дар ин ҷо мо фавран хосиятҳоро давр мезанем ва бевосита SetValue-ро даъват мекунем.

Барои возеҳият ва ҳамчун истинод, ман як усули соддаеро татбиқ кардам, ки арзишҳои ҷуфтҳои коррелятсияи онҳоро мустақиман ба майдонҳои объект менависад. Префикс - Дастӣ.

Акнун биёед BenchmarkDotNet-ро гирем ва иҷрои онро тафтиш кунем. Ва ногаҳон... (спойлер - ин натиҷаи дуруст нест, тафсилот дар зер оварда шудааст)

Мақолаи бемуваффақият дар бораи суръатбахшии инъикос

Мо дар ин ҷо чӣ мебинем? Усулҳое, ки префикси Fast-ро ғолибан ба даст меоранд, тақрибан дар ҳама гузаришҳо нисбат ба усулҳои префикси суст сусттар мешаванд. Ин хам ба таксимот ва хам ба суръати кор дахл дорад. Аз тарафи дигар, татбиқи зебо ва зебои харитасозӣ бо истифода аз усулҳои LINQ, ки барои ин дар ҳар ҷое ки имконпазир пешбинӣ шудаанд, баръакс, ҳосилнокиро хеле коҳиш медиҳад. Фарқият дар тартиб аст. Тамоюл бо шумораи гуногуни гузаришҳо тағир намеёбад. Ягона фарқият дар миқёс аст. Бо LINQ он 4 - 200 маротиба сусттар аст, тақрибан дар ҳамон миқёс ахлот бештар аст.

изофот

Ман ба чашмони худ бовар накардам, аммо муҳимтар аз ҳама, ҳамкори мо ба чашмони ман ва рамзи ман бовар накард - Дмитрий Тихонов 0x1000000. Пас аз ду маротиба тафтиш кардани ҳалли ман, ӯ ба таври олиҷаноб хатоеро кашф ва қайд кард, ки ман аз сабаби як қатор тағиротҳо дар татбиқ, аз аввал то ниҳоӣ аз даст додам. Пас аз ислоҳи хатои пайдошуда дар танзимоти Moq, ҳама натиҷаҳо ба ҷои худ афтоданд. Тибқи натиҷаҳои санҷиши такрорӣ, тамоюли асосӣ тағир намеёбад - LINQ то ҳол ба иҷроиш бештар аз инъикос таъсир мерасонад. Бо вуҷуди ин, хуб аст, ки кор бо compilation Expression беҳуда анҷом дода намешавад ва натиҷа ҳам дар тақсимот ва ҳам дар вақти иҷро намоён аст. Оғози аввал, вақте ки майдонҳои статикӣ оғоз карда мешаванд, барои усули "тез" табиатан сусттар аст, аммо баъд вазъ тағйир меёбад.

Ин аст натиҷаи санҷиши такрорӣ:

Мақолаи бемуваффақият дар бораи суръатбахшии инъикос

Хулоса: ҳангоми истифодаи рефлексия дар корхона зарурати махсус барои кор кардан ба ҳилаҳо вуҷуд надорад - LINQ маҳсулнокии бештарро истеъмол мекунад. Бо вуҷуди ин, дар усулҳои сарбории баланд, ки оптимизатсияро талаб мекунанд, шумо метавонед инъикосро дар шакли инициализаторҳо ва компиляторҳои вакилӣ захира кунед, ки он гоҳ мантиқи "зуд" -ро таъмин мекунад. Бо ин роҳ шумо метавонед ҳам чандирии инъикос ва суръати барномаро нигоҳ доред.

Рамзи муқоисавӣ дар ин ҷо дастрас аст. Ҳар кас метавонад суханони маро дубора тафтиш кунад:
Санҷишҳои HabraReflection

PS: Рамзи санҷишҳо IoC-ро истифода мебарад ва дар нишондиҳандаҳо он сохтори возеҳро истифода мебарад. Гап дар он аст, ки дар татбиқи ниҳоӣ ман ҳама омилҳоеро, ки метавонанд ба кор таъсир расонанд ва натиҷаро ғавғо гардонанд, қатъ кардам.

PPS: Ташаккур ба корбар Дмитрий Тихонов @0x1000000 барои ошкор кардани хатои ман дар танзими Moq, ки ба ченакҳои аввал таъсир расонд. Агар касе аз хонандагон кармаи кофӣ дошта бошад, лутфан лайк монед. Мард истод, мард хонд, мард ду маротиба санҷида хаторо нишон дод. Ман фикр мекунам, ки ин сазовори эҳтиром ва ҳамдардӣ аст.

PPPS: ташаккур ба хонандаи бодиққат, ки ба қаъри услуб ва тарроҳӣ расид. Ман тарафдори якрангӣ ва роҳат ҳастам. Дипломатияи презентатсия бисёр чизҳоро орзу мекунад, аммо ман танқидро ба назар гирифтам. Ман снарядро мепурсам.

Манбаъ: will.com

Илова Эзоҳ