چند وقت پیش توی یکی از شرکت های ایران استخدام شدم و از همون روز روی پروژه های مختلف مشغول فعالیت شدم تا بعد از حدود یک سال روی یکی از پروژه ها موندگار شدم, ه رچی حجم داده های داخل دیتابیس بیشتر و بیشتر میشد(برخی از جداول بالای چند میلیارد دیتا) یک چیزی توی سیستم داشت خودنمایی میکرد, اون هم کند شدن بیش از حد سیستم بود مخصوصا وقتی قرار بود گزارش بگیریم, کاری که انجام دادم بهبود سرعت این پروژه و اعمال یک سری تغییرات در سطح فریم ورک بود که باعث شد در بعضی قسمت های پروژه تا ده برابر سرعت بیشتر بشه و توی بعضی صفحات مدت زمان انتظار از بیست دقیقه برسه به حدود سه ثانیه, امروز گفتم یکی از این کارهارو که باعث افزایش سرعت و پرفورمنس شد رو بنویسم.
از اونجایی که این پروژه روی یک فریم ورک اختصاصی که داخل شرکت پیاده سازی شده بود اولین قدم برای من آنالیز کردن پروژه بود تا بفهمم عملیاتی که میخوام سرعتش رو بهبود بدم چی هستش, برای این که بتونم به حداکثر پرفورمنس مد نظر خودم برسم متوجه شدم تو یکی از پروژه ها برنامه نویس قبلی اومده یکی از فیلد ها private رو با کمک reflection دستکاری میکنه و همین موضوع یکی از دلایل کند بودن اجرای متد بودش(شاید اعداد و ارقامی که میخوام بنویسم اولش بگین چند نانوثانیه هیچ تاثیری نداره ولی قسمت اول رو دوباره بخونین تا دستتون بیاد که همین نانو ثانیه ها وقتی برای حجم بالای دیتا باشه چه تاثیری روی پروژه داره)
برای این که متوجه بشین دقیقا داستان چی بود تصویر زیر رو نگاه کنید
خب همون طوری که توی بالا میبیند یک کلاس داریم که یه متغیر private داخلش هستش که برنامه نویس قبلی به خاطر نیاز پروژه باید حتما این مقدار رو تغییر میداد یا یه آبجکت جدید از این کلاس ایجاد میکرد چون سربار ایجاد آبجکت جدید خیلی بالا بود اومده بود با reflection مقدار این متغیر رو تغییر میداد که موفق هم شده بود که پرفورمنس رو بالا ببره ولی این روش خیلی هم بهینه نیستش
خب تصویر بالا کدی بود که اولین بار نوشته شده بود و زمان اجرای این کار هم روی سیستم من حدود 1440 نانوثانیه بود
اومدم اول این کد رو کمی بهینه تر کردم و field lookup رو کش کردم تا فقط یک بار در زمان اولین اجرا درست بشه که نتیجه شد کد زیر:
و بعد از اجرا کردن این متد نتیجه اجرا هم شد حدود 1332 نانوثانیه,
این کد هم سریعتر از کد قبلی اجرا شد و هم بدنه متد خیلی تمیزتر ولی باز هم جوابگوی کار ما نبودتوی واقعیت فقط چند درصد کد ما سریعتر شده بود ولی این سریع بودن خیلی به چشم کاربر نمیومد و باز راضی کننده نبود, به خاطر همین مجبور شدم یه کار دیگه بکنم, یه خورده با کد ها سر و کله زدم دیدم با استفاده از Expression و Reflection اجرای کد سریعتر از این نمیشه, خب یه انتخاب جدید پیش روم بود باید انتخابش میکردم, دستکاری مستقیم متغیر با استفاده از کد های IL, دست به کار شدم و نتیجه شد کد زیر:
وقتی این پروژه رو اجرا کردم چیزی که دیدم شدیدا هیجان زده ام کرد, زمان اجرای این کد فوق العاده تر از اون چیزی هستش که میشه تصور کرد در حدود یک و نیم نانوثانیه
برای این که ببینم این کد چقده سریع هستش اومدم یه متغیر دیگه داخل کلاس تعریف کردم و از نوع public گذاشتمش و کد رو اجرا کردم
دست آخر همه کد ها رو گذاشتم کنار هم و اجرا کردم تا نتیجه رو راحت تر بشه مقایسه کرد:
همون طوری که توی عکس میتونید ببینید همین یک تغییر کوچیک باعث شد تا کد نزدیک به 1440 بار سریعتر اجرا بشه, شاید بگین این اعداد به نانوثانیه هستش و اصلا به چشم نمیاد ولی کافیه در نظر بگیرین وقتی که حداقل دیتایی که قراره این عملیات روش انجام بشه به یک میلیون رکورد برسه و قرار باشه این عملیات تکراری فقط روی یک فیلد انجام بشه میشه حدود یک و نیم ثانیه و اگر قرارباشه این عملیات رو مانند چیزی که توی پروژه ما بود(ایجاد یه آبجکت و مقدار دهی همه متغیرهاش به متد اول) برای یک کلاس با بیست تا فیلد میشه حدود 30 ثانیه