عڪاسي کي تيز ڪرڻ بابت ناڪام مضمون

مان فوري طور تي مضمون جي عنوان جي وضاحت ڪندس. اصل منصوبو هڪ سادي پر حقيقي مثال استعمال ڪندي عڪاسي جي استعمال کي تيز ڪرڻ بابت سٺي ۽ قابل اعتماد صلاح ڏيڻ هو، پر بينچ مارڪنگ دوران اهو ثابت ٿيو ته عڪاسي ايترو سست ناهي جيترو مون سوچيو، LINQ منهنجي خوابن جي ڀيٽ ۾ سست آهي. پر آخر ۾ معلوم ٿيو ته مون به ماپ ۾ غلطي ڪئي... هن زندگيءَ جي ڪهاڻيءَ جا تفصيل هيٺ ۽ تبصرن ۾ آهن. جيئن ته مثال بلڪل عام آهي ۽ اصول ۾ لاڳو ڪيو ويو آهي جيئن عام طور تي هڪ ڪمپني ۾ ڪيو ويندو آهي، اهو ڪافي دلچسپ ٿي ويو، جيئن مون کي لڳي ٿو، زندگي جو مظاهرو: مضمون جي مکيه موضوع جي رفتار تي اثر هو. خارجي منطق جي ڪري قابل ذڪر نه آهي: Moq، Autofac، EF Core ۽ ٻيا "bandings".

مون هن آرٽيڪل جي تاثر هيٺ ڪم ڪرڻ شروع ڪيو: ڇو ته عڪس سست آهي

جئين توهان ڏسي سگهو ٿا، ليکڪ سفارش ڪري ٿو ته مرتب ڪيل نمائندن کي استعمال ڪرڻ بجاءِ سڌو سنئون موٽڻ واري قسم جي طريقن کي ڪال ڪرڻ جو هڪ بهترين طريقو آهي ايپليڪيشن کي تيز ڪرڻ لاءِ. اتي، يقينا، IL اخراج آهي، پر مان ان کان بچڻ چاهيان ٿو، ڇاڪاڻ ته اهو ڪم ڪرڻ لاء سڀ کان وڌيڪ محنت وارو طريقو آهي، جيڪو غلطين سان ڀريل آهي.

ان ڳالهه تي غور ڪندي ته مون هميشه فڪر جي رفتار بابت هڪجهڙائي رکي آهي، مون خاص طور تي ليکڪ جي نتيجن تي سوال ڪرڻ جو ارادو نه ڪيو هو.

مون کي اڪثر انٽرپرائز ۾ عڪاسي جي غير معمولي استعمال سان منهن ڏيڻو پوي ٿو. قسم ورتو وڃي ٿو. ملڪيت بابت ڄاڻ ورتي وئي آهي. SetValue طريقو سڏيو ويندو آهي ۽ هرڪو خوش ٿيو. قيمت ٽارگيٽ فيلڊ ۾ اچي چڪو آهي، هرڪو خوش آهي. تمام هوشيار ماڻهو - سينيئر ۽ ٽيم ليڊز - انهن جي ايڪسٽينشن کي اعتراض ڪرڻ لاءِ لکن ٿا، اهڙي بي بنياد عمل جي بنياد تي هڪ قسم جي ٻئي قسم جي ”آفاقي“ نقشن تي. جوهر عام طور تي هي آهي: اسان سڀ فيلڊ وٺون ٿا، سڀئي ملڪيتون وٺون ٿا، انهن کي ٻيهر ڏيون ٿا: جيڪڏهن قسم جي ميمبرن جا نالا ملن ٿا، اسان SetValue تي عمل ڪريون ٿا. وقت بوقت اسان غلطين جي ڪري استثنا کي پڪڙيندا آهيون جتي اسان کي ڪنهن هڪ قسم ۾ ڪجهه ملڪيت نه ملندي آهي، پر هتي به هڪ طريقو آهي جيڪو ڪارڪردگي بهتر ڪري ٿو. ڪوشش ڪريو / پڪڙيو.

مون ڏٺو آهي ته ماڻهن کي مڪمل طور تي هٿياربند هجڻ جي بغير پارسر ۽ ميپرز کي ٻيهر ٺاهيو ويو آهي ته انهن جي اڳيان مشينون ڪيئن ڪم ڪن ٿيون. مون ڏٺو آهي ته ماڻهن کي حڪمت عملين جي پويان، انٽرفيس جي پويان، انجيڪشن جي پويان انهن جي غير جانبدار عملن کي لڪايو آهي، ڄڻ ته اهو بعد ۾ بيڪانيا کي عذر ڪندو. اهڙين حقيقتن تي مون پنهنجي نڙي مٿي ڪئي. حقيقت ۾، مون حقيقي ڪارڪردگي جي لڪير کي ماپ نه ڪيو، ۽، جيڪڏهن ممڪن هجي، مون صرف ان تي عمل درآمد کي وڌيڪ "بهترين" ۾ تبديل ڪيو جيڪڏهن آئون ان تي هٿ حاصل ڪري سگهان. تنهن ڪري، پهرين ماپن تي بحث ڪيو ويو آهي مون کي سنجيده مونجهارو.

منهنجو خيال آهي ته توهان مان ڪيترائي، ريڪٽر يا ٻيا نظرياتي پڙهندڙ، هڪ مڪمل طور تي منصفانه بيان ۾ آيا آهن ته ڪوڊ ۾ عڪس هڪ رجحان آهي جيڪو ايپليڪيشن جي ڪارڪردگي تي انتهائي منفي اثر آهي.

ڪال ڪرڻ جي عڪاسي CLR کي مجبور ڪري ٿي اسيمبلين مان وڃڻ لاءِ جنهن کي انهن جي ضرورت آهي ، انهن جي ميٽا ڊيٽا کي ڇڪيو ، انهن کي پارس ڪريو ، وغيره. ان کان علاوه، عڪاسي جڏهن ته ترتيبن کي پار ڪندي وڏي مقدار جي ميموري کي مختص ڪري ٿي. اسان ميموري استعمال ڪري رهيا آهيون، CLR GC کي ظاهر ڪري ٿو ۽ فريز شروع ٿئي ٿو. اهو واضح طور تي سست هجڻ گهرجي، مون تي يقين رکو. جديد پروڊڪشن سرورز يا ڪلائوڊ مشينن تي ياداشت جي وڏي مقدار اعليٰ پروسيسنگ تاخير کي روڪي نه ٿي. حقيقت ۾، وڌيڪ ياداشت، وڌيڪ ممڪن آهي ته توهان نوٽيس ڪيو ته GC ڪيئن ڪم ڪندو آهي. عڪاسي، نظريي ۾، هن لاءِ هڪ اضافي ڳاڙهي رڳ آهي.

بهرحال، اسان سڀ استعمال ڪندا آهيون IoC ڪنٽينر ۽ تاريخ ميپر، جنهن جو آپريٽنگ اصول پڻ عڪاسي تي ٻڌل آهي، پر عام طور تي انهن جي ڪارڪردگي بابت ڪو سوال ناهي. نه، نه ان ڪري جو انحصار جو تعارف ۽ خارجي محدود حوالن جي ماڊلن کان خلاصو ايترو ضروري آهي ته اسان کي هر صورت ۾ ڪارڪردگيءَ کي قربان ڪرڻو پوندو. هر شي آسان آهي - اهو واقعي ڪارڪردگي تي اثر انداز نٿو ڪري.

حقيقت اها آهي ته سڀ کان وڌيڪ عام فريم ورڪ جيڪي عڪاسي ٽيڪنالاجي تي ٻڌل آهن انهن کي وڌيڪ بهتر طريقي سان ڪم ڪرڻ لاء سڀني قسمن جي چالن کي استعمال ڪن ٿا. عام طور تي هي هڪ ڪيش آهي. عام طور تي اهي ايڪسپريس ۽ نمائندا آهن اظهار جي وڻ مان مرتب ڪيل. ساڳيو آٽو ميپر هڪ مقابلي واري ڊڪشنري کي برقرار رکي ٿو جيڪو قسمن سان ملندو آهي افعال سان جيڪي هڪ ٻئي ۾ تبديل ڪري سگھن ٿا بغير ڪنهن کي موٽڻ جي.

اهو ڪيئن حاصل آهي؟ لازمي طور تي، اهو منطق کان مختلف ناهي ته پليٽ فارم پاڻ کي JIT ڪوڊ ٺاهڻ لاء استعمال ڪري ٿو. جڏهن هڪ طريقو پهريون ڀيرو سڏيو ويندو آهي، اهو مرتب ڪيو ويندو آهي (۽، ها، اهو عمل تيز نه آهي)؛ ايندڙ ڪالن تي، ڪنٽرول اڳ ۾ ئي مرتب ڪيل طريقي ڏانهن منتقل ڪيو ويندو آهي، ۽ ڪارڪردگي ۾ ڪا خاص گهٽتائي نه هوندي.

اسان جي صورت ۾، توھان پڻ استعمال ڪري سگھو ٿا JIT تاليف ۽ پوءِ مرتب ڪيل رويي کي استعمال ڪريو ساڳي ڪارڪردگي سان ان جي AOT هم منصبن سان. اظهار هن معاملي ۾ اسان جي مدد لاء ايندا.

سوال ۾ اصول مختصر طور تي هن ريت ترتيب ڏئي سگهجي ٿو:
توھان کي ظاھر ڪرڻ جي آخري نتيجي کي ھڪڙي نمائندي جي طور تي ڪيش ڪرڻ گھرجي جنھن ۾ مرتب ٿيل فنڪشن شامل آھي. اهو توهان جي قسم جي شعبن ۾ قسم جي معلومات سان سڀني ضروري شين کي ڪيش ڪرڻ جو احساس پڻ ڪري ٿو، ڪم ڪندڙ، جيڪي شيون کان ٻاهر محفوظ ٿيل آهن.

ان ۾ منطق آهي. عام فهم اسان کي ٻڌائي ٿو ته جيڪڏهن ڪا شيءِ مرتب ۽ ڪيش ڪري سگهجي ٿي، ته پوءِ اهو ٿيڻ گهرجي.

اڳتي ڏسندي، اهو چوڻ گهرجي ته ڪشش سان ڪم ڪرڻ ۾ ڪيش ان جا فائدا آهن، جيتوڻيڪ جيڪڏهن توهان اظهار جي ترتيب ڏيڻ جو تجويز ڪيل طريقو استعمال نٿا ڪريو. دراصل، هتي آئون صرف مضمون جي ليکڪ جي ٿيسز کي ورجائي رهيو آهيان جنهن جو مون مٿي ذڪر ڪيو آهي.

هاڻي ڪوڊ جي باري ۾. اچو ته هڪ مثال تي نظر رکون جيڪو منهنجي تازي درد تي ٻڌل آهي جيڪو مون کي هڪ سنگين ڪريڊٽ اداري جي سنگين پيداوار ۾ منهن ڏيڻو پيو. سڀئي ادارا فرضي آهن ته جيئن ڪو به اندازو نه ڪري.

ڪجهه جوهر آهي. رابطو ٿيڻ ڏيو. هڪ معياري جسم سان اکر آهن، جن مان پارسر ۽ هائيڊيٽر اهي ساڳيون رابطا ٺاهيندا آهن. هڪ خط آيو، اسان ان کي پڙهيو، ان کي اهم-قدر جوڑوں ۾ پارس ڪيو، هڪ رابطو ٺاهيو، ۽ ان کي ڊيٽابيس ۾ محفوظ ڪيو.

اهو ابتدائي آهي. اچو ته چئو ته هڪ رابطي ۾ خاصيتون آهن مڪمل نالو، عمر ۽ رابطي جو فون. هي ڊيٽا خط ۾ منتقل ٿيل آهي. ڪاروبار پڻ مدد چاهي ٿو ته جلدي طور تي خط جي جسم ۾ جوڑوں ۾ اداري جي ملڪيت جي نقشي لاءِ نيون ڪيز شامل ڪرڻ جي قابل ٿي. ان صورت ۾ جيڪڏهن ڪنهن ٽيمپليٽ ۾ ٽائيپ ڪئي هجي يا جيڪڏهن رليز ٿيڻ کان اڳ اهو ضروري آهي ته فوري طور تي هڪ نئين پارٽنر کان ميپنگ شروع ڪئي وڃي، نئين فارميٽ کي ترتيب ڏيندي. ان کان پوء اسان هڪ نئين ميپنگ لاڳاپو شامل ڪري سگهون ٿا جيئن سستو ڊيٽا فڪس. يعني زندگيءَ جو مثال.

اسان لاڳو ڪريون ٿا، ٽيسٽ ٺاهيون. ڪم.

مان ڪوڊ مهيا نه ڪندس: ڪيترائي ذريعا آهن، ۽ اهي موجود آهن GitHub تي لنڪ ذريعي آرٽيڪل جي آخر ۾. توهان انهن کي لوڊ ڪري سگهو ٿا، انهن کي سڃاڻڻ کان ٻاهر تشدد ڪري سگهو ٿا ۽ انهن کي ماپ ڪري سگهو ٿا، جيئن اهو توهان جي صورت ۾ اثر انداز ٿيندو. مان صرف ٻن ٽيمپليٽ طريقن جو ڪوڊ ڏيندس جيڪي ھائيڊيٽر کي فرق ڪن ٿا، جنھن کي تيز ٿيڻو ھو، ھائيڊيٽر کان، جنھن کي سست ٿيڻو ھو.

منطق هن ريت آهي: ٽيمپليٽ جو طريقو بنيادي تجزيي منطق پاران ٺاهيل جوڙو حاصل ڪري ٿو. LINQ پرت parser آهي ۽ هائيڊيٽر جو بنيادي منطق آهي، جيڪو ڊيٽابيس جي حوالي سان هڪ درخواست ڪري ٿو ۽ ڪنجين کي پارسر جي جوڑوں سان موازنہ ڪري ٿو (انهن ڪمن لاءِ، مقابلي لاءِ LINQ کان سواءِ ڪوڊ آهي). اڳيون، جوڙو مکيه هائيڊريشن جي طريقي سان گذري ويا آهن ۽ جوڑوں جي قيمتن کي اداري جي لاڳاپيل ملڪيتن تي مقرر ڪيو ويو آهي.

”فاسٽ“ (Prefix Fast in benchmarks):

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

هتي اسان فوري طور تي ملڪيت کي نظرانداز ڪريون ٿا ۽ سڌو سنئون سيٽ ويلو کي سڏين ٿا.

وضاحت لاءِ ۽ هڪ حوالي جي طور تي، مون هڪ سادي طريقي تي عمل ڪيو آهي جيڪو انهن جي باهمي تعلقن جي قدرن کي سڌو اداري جي شعبن ۾ لکندو آهي. اڳڪٿي- دستور.

هاڻي اچو ته BenchmarkDotNet وٺو ۽ ڪارڪردگي جو جائزو وٺو. ۽ اوچتو ... (خراب ڪندڙ - اهو صحيح نتيجو نه آهي، تفصيل هيٺ ڏنل آهن)

عڪاسي کي تيز ڪرڻ بابت ناڪام مضمون

اسان هتي ڇا ٿا ڏسو؟ اهي طريقا جيڪي ڪاميابيءَ سان Fast اڳياڙي کي برداشت ڪن ٿا، تقريبن سڀني پاسن ۾ سست پريفڪس وارن طريقن جي ڀيٽ ۾ سست ثابت ٿين ٿا. اهو ٻنهي مختص ۽ ڪم جي رفتار لاء صحيح آهي. ٻئي طرف، MINQ طريقن کي استعمال ڪندي نقشي جو هڪ خوبصورت ۽ خوبصورت عمل جتي ممڪن هجي، ان جي برعڪس، پيداوار کي تمام گهڻو گھٽائي ٿو. فرق آرڊر جو آهي. پاسن جي مختلف نمبرن سان رجحان تبديل نٿو ٿئي. فرق صرف ماپ ۾ آهي. LINQ سان اهو 4 - 200 ڀيرا سست آهي، اتي تقريبن ساڳئي پيماني تي وڌيڪ گندگي آهي.

اپڊيٽ

مون کي پنهنجين اکين تي يقين نه آيو، پر وڌيڪ اهم ڳالهه ته، اسان جي ساٿيءَ کي نه ته منهنجي اکين تي يقين نه آيو ۽ نه ته منهنجي ڪوڊ تي. دمتري Tikhonov 0x1000000. منهنجي حل کي ٻه ڀيرا جانچڻ کان پوء، هن شاندار طور تي دريافت ڪيو ۽ هڪ غلطي جي نشاندهي ڪئي جيڪا مون کي ياد ڪيو ويو آهي عملدرآمد ۾ تبديلين جي ڪري، شروعاتي کان فائنل تائين. Moq سيٽ اپ ۾ مليل بگ کي درست ڪرڻ کان پوء، سڀئي نتيجا جاء تي ٿي ويا. ريٽسٽ نتيجن جي مطابق، مکيه رجحان تبديل نٿو ڪري - LINQ اڃا تائين ڪارڪردگي کان وڌيڪ اثر انداز ڪري ٿو. بهرحال، اهو سٺو آهي ته اظهار جي تاليف سان ڪم بيڪار نه ڪيو ويو آهي، ۽ نتيجو مختص ۽ عمل جي وقت ٻنهي ۾ نظر اچي ٿو. پهرين لانچ، جڏهن جامد شعبن جي شروعات ڪئي وئي آهي، قدرتي طور تي "تيز" طريقي لاء سست آهي، پر پوء صورتحال تبديل ٿي.

هتي ٻيهر امتحان جو نتيجو آهي:

عڪاسي کي تيز ڪرڻ بابت ناڪام مضمون

نتيجو: جڏهن هڪ ڪمپني ۾ عڪاسي استعمال ڪندي، چالن کي استعمال ڪرڻ جي ڪا خاص ضرورت ناهي - LINQ پيداوار کي وڌيڪ کائيندو. جڏهن ته، تيز لوڊ طريقن ۾ جيڪي اصلاح جي ضرورت هونديون آهن، توهان شروعاتي ۽ نمائندي ڪمپلرز جي صورت ۾ عکاس کي محفوظ ڪري سگهو ٿا، جيڪو پوء "تيز" منطق مهيا ڪندو. اهو طريقو توهان ٻنهي کي برقرار رکي سگهو ٿا عڪاسي جي لچڪ ۽ ايپليڪيشن جي رفتار.

بينچ مارڪ ڪوڊ هتي موجود آهي. ڪو به منهنجي لفظن کي ٻه ڀيرا چيڪ ڪري سگهي ٿو:
Habra Reflection Tests

پي ايس: ٽيسٽ ۾ ڪوڊ IoC استعمال ڪندو آهي، ۽ معيارن ۾ اهو هڪ واضح تعمير استعمال ڪندو آهي. حقيقت اها آهي ته حتمي عمل ۾ مون سڀني عنصر کي ڪٽي ڇڏيو آهي جيڪي ڪارڪردگي تي اثر انداز ڪري سگهن ٿا ۽ نتيجو شور ڪري سگهي ٿو.

پي پي ايس: استعمال ڪندڙ جي مهرباني دمتري تيخونوف @0x1000000 Moq کي ترتيب ڏيڻ ۾ منهنجي غلطي کي دريافت ڪرڻ لاء، جنهن پهرين ماپ کي متاثر ڪيو. جيڪڏهن پڙهندڙن مان ڪنهن وٽ ڪافي ڪارناما آهن، مهرباني ڪري پسند ڪريو. ماڻهو روڪيو، ماڻهو پڙهي، ماڻهو ٻه ڀيرا چيڪ ڪيو ۽ غلطي جي نشاندهي ڪئي. مان سمجهان ٿو ته اها عزت ۽ همدردي جي لائق آهي.

PPPS: محتاط پڙهندڙن جي مهرباني، جيڪو انداز ۽ ڊزائن جي تري تائين پهچي ويو. مان يونيفارم ۽ سهولت لاءِ آهيان. پريزنٽيشن جي سفارتڪاري گهڻو ڪجهه ڇڏي ٿي، پر مون تنقيد کي حساب ۾ ورتو. مان پروجيڪٽ لاءِ پڇان ٿو.

جو ذريعو: www.habr.com

تبصرو شامل ڪريو