در این مقاله قصد دارم مواردی رو درباره بهینه سازی کد و بالا بردن کارایی آن بگم .

ما برای بهینه سازی کد نیازی به کد نویسی پیچیده نداریم ،همیشه باید از کدهای غیر ضروری پرهیز کرد ، زیرا باعث پیچیده تر شدن برنامه می شود  . البته این را باید بدانیم که برای تحقق بخشیدن به یکسری از برنامه ها و گذاشتن وظایف مختلف باید کدهای پیچیده هم نوشت .  پس باید از ابتدای برنامه بهترین راه حلها را با بهترین کارایی طراحی کنیم .

وقتی ما برنامه ای با سطوح مختلف و چند لایه می نویسیم ،باید اکثر مشکلات را حدس زده و برای بر طرف کردن آن اقدام کنیم  . هرچه این لایه ها بیشتر شود اشکالات هم به طور محسوسی افزایش

 می یابد ، و باید برای هر مشکل راه حلی اساسی مد نظر بگیریم زیرا با راه حل هایی ساده باز مشکل بر می گردد .متاسفانه راه حل قطعی وجو نداردفقط می توان  پس برای بروز کمتر این مشکل باید برنامه نویسان یک گروه بر اساس یک راه حل درست عمل کنند  .

این مقاله به شما کمک می کند تا در فرایند هایی مانند  : ذخیره یک متغیر برای استفاده دوباره  ، استفاده از switch ها و اعمالی مانند اینها که اکثر برنامه نویسان با آن آشنایی دارن!

 

 

Tools

 ما برای تست برنامه ها از ابزاری مانند Nunit استفاده می کنیم ، با این حال باید خود دست به کار شویم . یکی از مهمترین عوامل در هر نرم افزاری زمان اجرا شدن کدهایی مانند (Delegate , Meyjod, ..) است . پس هرچه بتوانیم زمان دقیق تری از زمان مانند یک میلیونیم ثانیه یا nanosecond از اجرای یک دسته کد بدست آوریم بهتر است . برای امتحان این منظور از حلقه زیر استفاده می کنیم  . در این حلقه ما زمان قبل از اجرای کد و زمان بعد اجرای کد را حساب می کنیم و در آخر از هم تفریق می کنیم ، بعد این مدت زمان نسبت به تعداد تکرارها تقسیم می شود  ، زمان محاسبه شده قیمت هر تکرا را می رساند ، به کد زیر توجه کنید :


            int loopCount = 1000000000;

            long startTime, endTime;

            double nanoseconds;

 

            startTime = DateTime.Now.Ticks * 100;

            for (int x = 0; x < loopCount; x++)

            {

                // put the code to be tested here

            }

            endTime = DateTime.Now.Ticks * 100;

 nanoseconds = ((double)(endTime - startTime)) / ((double)loopCount);     MessageBox.Show(nanoseconds.ToString("F") + " ns per operation");

 

زمانی که این تست ساده را انجام می دهیم مهم است که دو چیز را یادتان باشد . اول اینکه کوچکترین تغییر یا نوسانی چیز طبیعی است  . بنابراین برای بدست آوردن نتایج دقیق باید چندین بار یک تست را انجام دهید . ممکن است اگر این تست را بعد از مقدار دهی اولیه برنامه انجام دهید به کندی انجام شود.

اگر شما دیدید که نتایج با هم ناسازگارند ، بهترین راه حل استفاده از تست حلقه بیشتر است . پس این راه حل هزینه نسبی بهتر را در اختیار شما می گذارد تا بتوانید با دید روشنتری به کد نگاه کنید .

یک دیگر از ابزار مهم disassmbler یا ildasm.exe  است . این ابزار به شما کمک می کند تا فرضیه هایی را که در قبل زدید درس است یا نه  . اکثر کاربران دات نت کم و بیش از IL می دانند  ، ولی برای شروع می توانید از کتاب آقای Serge Lidin's استفاده کنید .

همچنین شما می توانید برای decompile (عملی معکوس کامپایل کردن) کردن برنامه از ابزار رایگان که در سایت www.aisto.com/roeder/dotnet/ می توانید دانلود کنید .

 

Working with Objects and Value Types

استفاده از اشیا گران قیمت است  ، قسمتی به خاطر اینکه حافظه را اشغال می کند (که البته در دات نت بهینه شده است) و قسمتی دیگر به خاطر این که باید شی از بین برود (Destroy) . از بین بردن یک شی زمان بیشتری را نسبت به ایجاد و مقدار دهی آن می برد ، به خصوص اگر شی دارای روتین های سفارشی باشد  ، در این جا است که Grabage Collector دست به کار می شود و شی ای که در حافظه فضای اصافی گرفته است خراب می کند تا حافظه آزاد شود  .  اطلاعات کافی و درک کلی از

Garbage Collector و تاثیر آن در برنامه یکی از ضروریات است . یکی از موارد مهم درباره Garbage که دانستن آن ضرورت دارد این است که Garbage Collector اشیا را به سه قسمت تقسیم می کند

( که  به آن Generation می گویند)   : 0 و 1 و 2  . اکثر اشیا برای در قسمت 0 و اگر استفاده از آن طولانی مدت باشد در 1 و کمتر اتفاق بیفتد که در 2 انتقال یابد . پس در نتیجه برای هر Generation که بالا می رود و یک شی نابود می شود  ، هزینه به نسبت بیشتر می شود  . به همین دلیل باید از ایجاد اشیای غیر ضروری پرهیز کنیم و باید هر شی ای را که کارمان به آن تمام شد سریعا نابود کنید(Destroy)

البته بعضی از اشیا نیاز است که تا زمانی که برنامه باز است آن شی هم باشد .

مقدار دهی و نمونه سازی کند

در الگوی Singleton اغلب یک شی global از کلاس ایجاد می کنیم . بعضی از اوقات این اشیا در طول برنامه مورد استفاده قرار نمی گیرد .  بعضی اوقات برای تمرین خوب است که در ایجاد اشیا تاخیر بیندازیم تا زمانی که به آن احتیاج داشته باشیم  ، مگر اینکه نیاز مخصوصی به آن داشته باشیم مانند  : ایجاد اشیا برای اتصال به پایگاه داده  ، مقدار دهی اولیه  .

استفاده از الگوهای  Double Checked Locking در این موقعیت ها می تواند مفید باشد . به  عنوان راهی برای دوری از هماهنگ سازی (synchronization) است   ، همچنین

مقدار دهی کند (Lazy initialization) تکنیکی است که باعث می شود که با ایجاد اشیای کمتر کارایی برنامه بالا برود .

 

دوری از کلاس های مخرب

کلاسهای مخرب باعث می شود تا بار اضافی بر روی Garbage Collector  بیاید ،  زیرا شی  Finalize

می شود قبل از اینکه از حافظه آزاد شود  . و استفاده از Finalizer  ها نشان دهنده مدیریت پایین برنامه است.

 

Casting و Boxing / Unboxing

Casting یک نوع تبدیل نوعی ، به اینصورت که یک type به type  دیگری در زمان اجرا تبدیل می شود   ، و همچنین  تبدیل (Value Type) را به (Refrence Type)  را Boxing می گویند . عمل کردن این مورد حجم زیادی را در کلاسهای (collection) می گیرد ، البته استثنا هایی هم وجود دارد مانند کلاس  StringDictionary  . برای مثال زمانی که شما Int32 را در  ArrayList()می ریزید ، در اول به حالت Box می شود هر بار که مقدار از روی آن خوانده شود ، اول Unbox می شود  ، بعد مقادیر را بر می گرداند .

 

 

 

Trusting the Garbage Collector

بعضی از برنامه نویسان نگران تخصیص حافظه در برنامه های خود هستند ، که البته می توان با استفاده از کتابخانه های (دات نت) این خلا رو تا حدودی بر طرف کرد . Garbage Collector ها  یک فرایند نسبتا

 پر هزینه ای هستند . در سیستم GC دات نت شی یک نوع تاخیر وجود دارد که تا زمانی که حافظه موجود است شی هم موجود باشد ، مگر اینکه بخواهد مدت طولانی تری را مانند (Generation 1 , 2)

در حافظه باقش بماند . برای مثال برنامه Hello World!  که با کنسول نوشته شده است حدود 15 مگابایت یا بیشتر حافظه اشغال می کند . پس با این حساب از GC.Collect استفاده نکنید مگر اینکه واقعا می دانید دارید چکار می کنید !

 ______

در پست های بعدی ادامه این مقاله رو هم می زارم ، لطفا نظرات خود را در مورد این پست اعلام کنید .