PDA

View Full Version : گفتگو: بهینه کردن و بالا بردن Performance برنامه ها



masoodp666
یک شنبه 20 مرداد 1387, 08:55 صبح
درود

من میخوام یه تاپیک جامع (اگه بشه) در مورد چگونگی بهینه کردن و بهتر کردن Performance برنامه های Visual Studio رو مطرح کنم در نتیجه از اساتید بزرگ در این زمینه که کمک میخواستم که از تجربه های با ارزش خودشون ما رو بی نصیب نذارن.

برای شروع فرض کنیم یه برنامه که از یه solution و چندین project و چند web service تشکیل شده و یه بانک SQL Server هم از طریق شبکه به برنامه اتصال دارد.

حالا سوال اینه که چه راهکار هایی وجود داره تا برنامه رو بشه هم در زمان develop و هم در زمان نصب در محل client به بهترین performance و بیشترین سرعت رسوند تا کمترین resource رو استفاده کنه و حجم ram رو زیادی اشغال نکنه ؟

من خودم اطلاعات زیادی در این زمینه ندارم بعضی از چیزهایی میدونم اینها هستند:
1- تا جایی که میشود از DataType , Object استفاده نشود.
2- دوری کردن از متغییر های Public تا سر حد امکان و استفاده از متغییرهای Local به دلیل اینکه متغییرهای عمومی در حافظه بیشتر ماندگار میشوند. بهتری راه حل برای استفاده از متغییر ها ساختن آنها درست در همان لحظه استفاده است.
3- اجتناب از استفاده از Loop ها به دلیل اینکه حجم باایی از محاسبات رو به خودشون اختصاص میدهند
4- .....

برای شروع از اساتید دیگه هم راهنمایی میخواهم. امیدوارم که این تاپیک بتونه کمک زیادی به برنامه نویسان عزیز بکنه. در ادامه هم مسایل دیگه ای هم هست که خواهم گفت. ممنون

masoodp666
یک شنبه 20 مرداد 1387, 17:05 عصر
یعنی واقعا هیچ دوستی در این زمینه مشکلی نداشته ؟!
تمام برنامه نویسان ایران بهینه ترین کدها رو مینویسن ؟ اتفاقا منم دنبال همین هستم.

تجاربتون رو در اختیار ما هم بگذارید.

masoodp666
یک شنبه 20 مرداد 1387, 17:07 عصر
اگه از مثال من خوشتون نیومده یه مثال از خودتون فرض کنید.

reza6384
یک شنبه 20 مرداد 1387, 17:47 عصر
هر کسی در سطح خودش کار می کنه. Optimize کردن برنامه کاریه که باید از بدو نوشتن کد شروع بشه تا آسون باشه. من فکر می کنم اکثریت به فکر این هستن که برنامه نیازهای کاربر رو براورده کنه و Bug هم نداشته باشه. حالا سرعتش اگر خیلی اذیت نکرد مهم نیست. اینی که شما می فرمایید کاملا درسته. اما بهش کم توجه میشه.

hdv212
یک شنبه 20 مرداد 1387, 21:36 عصر
2- دوری کردن از متغییر های Public تا سر حد امکان و استفاده از متغییرهای Local به دلیل اینکه متغییرهای عمومی در حافظه بیشتر ماندگار میشوند.
در دنیای دات نت، چنین نیست، چون مدیریت حافظه بر عهده ی Clr میباشد و یکی از آیتمهایی که Clr رو برای پاکسازی حافظه Fire میکنه، دنبال کردن متغیرهایی هست که ارجاع به اونا به حداقل و یا صفر میرسه، یعنی این متغیرها تا مدتی در برنامه بلا استفاده هستند و هیچ کدی از اونا استفاده نمیکنه، اینجاست که Clr این متغیر رو برای پاکسازی علامت گذاری میکنه و زمانی که Garbrage Collector شروع به پاکسازی حافظه میکنه این متغیر هم از حافظه پاک میشه و فضای اختصاص یافته به آن آزاد میشه.

در مورد افزایش کارایی نرم افزارها، خصوصا نرم افزارهای دیتابیس که مد نظر شما بود، علاوه بر اینکه شیوه ی طراحی نرم افزار و همچنین کد نویسی مهمه، مدیریت دیتابیس بر روی سرور هم مهمه، حتی شایدم بیشتر، چون اگه نرم افزاری به درستی طراحی شده باشه، اما دیتابیس اون به درستی طراحی و پیکربندی نشده باشه، خب بالطبع، برنامه کارایی مورد انتظار رو نخواهد داشت، به خاطر همین Performance برنامه ها جدای از طراحی و کد نویسی، به فاکتور های دیگه ای هم بستگی داره که خارج از دست برنامه نویسه!

masoodp666
دوشنبه 21 مرداد 1387, 10:05 صبح
در دنیای دات نت، چنین نیست، چون مدیریت حافظه بر عهده ی Clr میباشد و یکی از آیتمهایی که Clr رو برای پاکسازی حافظه Fire میکنه، دنبال کردن متغیرهایی هست که ارجاع به اونا به حداقل و یا صفر میرسه، یعنی این متغیرها تا مدتی در برنامه بلا استفاده هستند و هیچ کدی از اونا استفاده نمیکنه، اینجاست که Clr این متغیر رو برای پاکسازی علامت گذاری میکنه و زمانی که( Garbrage Collector (GC شروع به پاکسازی حافظه میکنه این متغیر هم از حافظه پاک میشه و فضای اختصاص یافته به آن آزاد میشه.


اتفاقا یکی از مشکلات همین Garbage Collector هستش به این صورت که زمان مشخصی ندارد. آبجکت هایی که Value Type هستن چون در Stack ذخیره میشن به سرعت در زمان پایان Life Time شان (که بسته به استفاده اونها داره مثلا به محض پایان یافتن function یا sub) از حافظه پاک خواهند شد.

ولی این داستان برای آبجکتهای Reference Type به صورت دیگری هست. این آبجکتها فقط رفرنسشون پاک میشه و خود فضای واقعی چون در Heap قرار داره باید توسط GC از بین بره و از طرفی چون GC زمانی این کار رو انجام میده که به اصطلاح سر CPU خلوت بشه در نتیجه زمان مشخصی رو نمیشه برای اون در نظر گرفت.

و حالا در نظر بگیرید که برنامه بزرگ باشه و دائم در حال محاسبات و ساختن آبجکت های فراوان. در نتیجه حافظه پر خواهد شد و out of memory خواهد داد. و بنابراین یکی از راهها اینه که آبجکتها طوری تعریف بشن که در پایان استفاده Dispose بشن و به دست GC نیفتن.

علاوه بر تمام اینها به نظر من بیشتر، کدنویسی ها، باعث کند شدن برنامه ها میشوند. مثلا استفاده از qurey های زمان بر و سنگین و .... و در واقع نظر بنده این بود که دوستان تجربیات خودشون رو بگویند.

hdv212
دوشنبه 21 مرداد 1387, 18:20 عصر
ولی این داستان برای آبجکتهای Reference Type به صورت دیگری هست. این آبجکتها فقط رفرنسشون پاک میشه و خود فضای واقعی چون در Heap قرار داره باید توسط GC از بین بره و از طرفی چون GC زمانی این کار رو انجام میده که به اصطلاح سر CPU خلوت بشه در نتیجه زمان مشخصی رو نمیشه برای اون در نظر گرفت.
حالا اگه هیچ وقت سر CPU خلوت نشه چه اتفاقی میفته ؟
بدین شکل نیست، Clr زمانی GC (http://msdn.microsoft.com/en-us/library/system.gc.aspx) رو فراخوانی میکنه که برای اختصاص دادن حافظه به آبجکتهای جدید با کمبود حافظه مواجه میشه، به این ترتیب GC رو فراخوانی میکنه، به هر حال شما میتونید GC رو با فراخوانی GC.Collect (http://msdn.microsoft.com/en-us/library/xe0c2357.aspx) به صورت دستی فراخوانی کنید.

vcldeveloper
سه شنبه 22 مرداد 1387, 00:31 صبح
دوری کردن از متغییر های Public تا سر حد امکان و استفاده از متغییرهای Local به دلیل اینکه متغییرهای عمومی در حافظه بیشتر ماندگار میشوند. بهتری راه حل برای استفاده از متغییر ها ساختن آنها درست در همان لحظه استفاده است.
یکی از دوستان بحث مدیریت خودکار حافظه در دات نت را مطرح کردند، ولی جدای از آن بحث؛ فیلدهای Public شما در یک کلاس از نظر ماندگاری در حافظه، فرقی با فیلدهای Private ندارند. هر دو بخشی از داده های یک شی هستند که تا زمانی که شی از حافظه خارج نشده، در حافظه باقی می مانند. بحثی که شما مطرح کردید، برای متغیرهای Global در برنامه مطرح میشد. در #C چیزی به اسم متغیر Global نداریم، اما امکان ایجاد فیلدهای static هست. فیلدهای static بجای آنکه متعلق به یک نمونه از کلاس باشند، به خود کلاس تعلق دارند، به همین دلیل هم مشابه متغیرهای Global عمل می کنند.


ولی این داستان برای آبجکتهای Reference Type به صورت دیگری هست. این آبجکتها فقط رفرنسشون پاک میشه و خود فضای واقعی چون در Heap قرار داره باید توسط GC از بین بره و از طرفی چون GC زمانی این کار رو انجام میده که به اصطلاح سر CPU خلوت بشه در نتیجه زمان مشخصی رو نمیشه برای اون در نظر گرفت.
اینطور نیست که یک برنامه برای هر بایت از اطلاعاتی که نیاز داره، بالافاصله از سیستم عامل درخواست همان مقدار حافظه را بکند، و هر بار که خانه حافظه ایی آزاد شد، بالافاصله آن را تحویل سیستم عامل بده! بلکه حافظه بصورت قطعات تقریبا بزرگی از سیستم عامل گرفته میشه و به بخش های کوچکتری تقسیم میشه. برنامه با این بخش ها کار میکنه، اگر نیاز به حافظه بیشتری بود، یک قطعه تقریبا بزرگ دیگه ایی از سیستم عامل میگیره. وقتی هم که خانه ایی از حافظه آزاد میشه، برنامه بالافاصله آن را به سیستم عامل برنمی گردانه، بلکه آن را برای استفاده های بعدی در داخل خود برنامه رزرو میکنه، غیر از اینکه سیستم عامل واقعا به آن مقدار حافظه آزاد شده نیاز داشته باشه. پس موردی که شما بهش اشاره کردید، جای نگرانی خاصی نداره.
در ضمن، در سیستم عاملی مثل ویندوز، عملا شما محدودیت حافظه خاصی ندارید، چون از Page file برای نگهداری موقت داده ها استفاده میکنه، البته سرعت Page file بسیار کمتر از RAM هست.

Amir Oveisi
سه شنبه 22 مرداد 1387, 00:57 صبح
در حالت کلی این رو هم بنده هم عرض کنم که نرم افزارهای ایجاد شده NET. مشکل خاصی از نظر performance نخواهد داشت مگر اینکه در یکی از قسمت های طراحی و یا پیاده سازی بسیار غیر استاندارد و خارج از چهارچوب اصول NET. ‌و OOP عمل بشه.

موفق باشید
jooje

ASKaffash
سه شنبه 22 مرداد 1387, 08:14 صبح
سلام
من با hdv212 موافقم چون عمده ضعف نرم افزارهای کاربردی در بخش اتصالات پایگاه داده ای است و هر برنامه هر چقدر هم الگوریتم بدی داشته باشد یا از منابع بد استفاده کند سهم کمی را از کارائی دارد در ضمن استفاده از حلقه ها یک اجبار است ولی قبول دارم که بعضی از روشهای استفاده از حلقه ها زائد است و میتواند حلقه را حذف یا عملیات آنرا بهینه کرد اگر تست کرده باشید می بینید یک برنامه کاربردی به خودی خود خیلی کند نیست وقتی پای پایگاه داده باز میشود اختلاف برنامه شخص x با y از زمین است تا آسمان که طراحی اصولی پایگاه داده ایندکس ها استفاده نادرست از تریگرها و غیره فوق العاده تعیین کننده است

masoodp666
چهارشنبه 23 مرداد 1387, 09:28 صبح
بدین شکل نیست، Clr زمانی GC (http://msdn.microsoft.com/en-us/library/system.gc.aspx) رو فراخوانی میکنه که برای اختصاص دادن حافظه به آبجکتهای جدید با کمبود حافظه مواجه میشه

بنده هم همینو گفتم. این قضیه شاید در برنامه های کوچک زیاد احساس نشه ولی در برنامه های بزرگ کمی باعث کند شدن سرعت خواهد شد چون بهرحال حافظه Heap باید خالی بشه. ولی بهرحال فکر نکنم کسی با از بین بردن آبجکت بلافاصله بعد از پایان استفاده از آن مخالف باشه !


فیلدهای Public شما در یک کلاس از نظر ماندگاری در حافظه، فرقی با فیلدهای Private ندارند.

منظور شما این است که متغییر Local ای که بعد از پایان function یا void از بین میره و حافظه آزاد میشه فرقی با متغییر Public که تا زمان پایان و close برنامه در حافظه میماند ندارد !؟


طراحی اصولی پایگاه داده ایندکس ها استفاده نادرست از تریگرها و غیره فوق العاده تعیین کننده است

اگه به نظر شما اینطوریه در این زمینه بحث کنیم.

برای مثال تویه یه برنامه من دیدم که توی query از Having استفاده شده بود بجای استفاده از Where. در صورتیکه وقتی از Having استفاده میشه که بخواهیم روی "نتایج" یه query شرطی رو اعمال کنیم و چون Having میره و کل جواب query رو میاره داخل حافظه و بعد روی اون فیلتر میکنه در نتیجه از Where که همون فیلدهای درخواستی رو میاره بیشتر فضا و سرعت میگیره.
درنتیجه فقط زمانی باید از Having استفاده کرد که روی نتایج یه query بخواهیم فیلتر کنیم.

hdv212
چهارشنبه 23 مرداد 1387, 12:27 عصر
بنده هم همینو گفتم. این قضیه شاید در برنامه های کوچک زیاد احساس نشه ولی در برنامه های بزرگ کمی باعث کند شدن سرعت خواهد شد چون بهرحال حافظه Heap باید خالی بشه. ولی بهرحال فکر نکنم کسی با از بین بردن آبجکت بلافاصله بعد از پایان استفاده از آن مخالف باشه !

در دنیای دات نت و در حالت نرمال، اگر خود برنامه مشکلی در زمینه ی ساختار برنامه نویسی نداشته باشه، برنامه با فقدان حافظه مواجه نمیشه، چون همانطور که آقای کشاورز در پست شماره ی 8 ذکر کردند، زمانی که حافظه ی اختصاص داده شده به متغیری آزاد شد، اون فضا به سیستم عامل بر نمیگرده بلکه برای استفاده های بعدی برنامه رزرو میشه، همچنین در اینکه شما از Dispose استفاده کنید، مخالفتی نیست، ولی راه بهتری که مایکروسافت پیشنهاد میکنه استفاده از دستور using (http://msdn.microsoft.com/en-us/library/yh598w02.aspx) هست.


برای مثال تویه یه برنامه من دیدم که توی query از Having استفاده شده بود بجای استفاده از Where. در صورتیکه وقتی از Having استفاده میشه که بخواهیم روی "نتایج" یه query شرطی رو اعمال کنیم و چون Having میره و کل جواب query رو میاره داخل حافظه و بعد روی اون فیلتر میکنه در نتیجه از Where که همون فیلدهای درخواستی رو میاره بیشتر فضا و سرعت میگیره.
درنتیجه فقط زمانی باید از Having استفاده کرد که روی نتایج یه query بخواهیم فیلتر کنیم.
چنین نیست، زمانی از having استفاده میشه که از Aggregate Function ها در شرطمون استفاده کرده باشیم و استفاده از دستور where اصلا مجاز نیست و باعث ایجاد خطا میشه.

vcldeveloper
چهارشنبه 23 مرداد 1387, 13:07 عصر
منظور شما این است که متغییر Local ای که بعد از پایان function یا void از بین میره و حافظه آزاد میشه فرقی با متغییر Public که تا زمان پایان و close برنامه در حافظه میماند ندارد !؟

نه. منظور این نیست. وقتی می خواید یک متغیر لوکال در سطح یک تابع تعریف میشه را با چیزی مقایسه کنید، باید آن را با یک متغیر Global یا یک فیلد در یک کلاس مقایسه کنید. ولی شما آن را با یک حوزه تعریف فیلد، یعنی Public مقایسه کردید. در نتیجه تصور من این بود که شما دارید حوزه تعریف public را با حوزه تعریف دیگه ایی مثل private مقایسه می کنید.
در هر حال، در یک کلاس فرقی نمیکنه یک فیلد را در چه حوزه ایی تعریف کنید، اون فیلد تا زمانی که شی ایجاد شده در حافظه باشه، موجود هست. متغیرهای لوکالی که در سطح یک تابع تعریف میشند، با پایان یافتن تابع عمرشان تمام میشه.
البته باید دقت کرد که همیشه استفاده از حافظه کم موجب افزایش کارایی نمیشه! مثلا اگر شما یک string را در اندازه کوچکی داشته باشید و دائما آن را تغییر دهید و رشته های دیگری را به آن اضافه کنید، سربار ایجاد شده بیشتر از زمانی هست که شما یک string بزرگ دارید. همچین چیزی را در نحوه دریافت حافظه از سیستم عامل هم می بینیم. معمولا حافظه ایی بسیار بیشتر از مقدار مورد نیاز از سیستم عامل گرفته میشه، به این ترتیب نیاز به ارسال درخواست های بعدی به سیستم عامل کاهش پیدا میکنه و این خودش موجب کاهش سربار برنامه میشه.

به یک نکته هم توجه کنید، بهینه سازی روی هر چیزی جواب نمیده! بهینه سازی زمانی ارزش داره که شما برنامه را با یک Profiler بررسی کنید و بخش هایی از برنامه را که بیشترین ترافیک را دارند، شناسایی کنید، اون وقت روی بهینه کردن این بخش ها تمرکز کنید، وگرنه بهینه کردن کدی که صرفا یک بار اجرا میشه، یا احتمال اجرای آن در طول برنامه بسیار کم هست، ارزش خاصی نداره! در یک برنامه ویندوزی، اگر شما یک دستور اضافه در روال پردازش پیام یک پنجره بنویسید، تاثیر آن را بالافاصله مشاهده می کنید، اما اگر مثلا تابع نمایش یک دایالوگ باکس را بهینه کنید، تاثیر چندانی در کل پروژه احساس نمی کنید.

ASKaffash
چهارشنبه 23 مرداد 1387, 14:01 عصر
اگه به نظر شما اینطوریه در این زمینه بحث کنیم.
برای مثال تویه یه برنامه من دیدم که توی query از Having استفاده شده بود بجای استفاده از Where. در صورتیکه وقتی از Having استفاده میشه که بخواهیم روی "نتایج" یه query شرطی رو اعمال کنیم و چون Having میره و کل جواب query رو میاره داخل حافظه و بعد روی اون فیلتر میکنه در نتیجه از Where که همون فیلدهای درخواستی رو میاره بیشتر فضا و سرعت میگیره.
درنتیجه فقط زمانی باید از Having استفاده کرد که روی نتایج یه query بخواهیم فیلتر کنیم.

باسلام
این موضوع اگر مورد بحث قرار گیرد جزو این تالار نخواهد بود و باید در تالار مثل SQLServer مطرح شود.

openeyes
چهارشنبه 23 مرداد 1387, 19:07 عصر
قبلا تاپیکی در این مورد نوشته بودم
یک کتاب از مایکرو سافت در زمینه بهبود کارایی برنامه های دات نت
http://barnamenevis.org/forum/showthread.php?p=523960#post523960
کتاب خوبی هستش و در اکثر مورادی که شما با اون کار می کنید مطلب داره مثل SQL server و ASP.NET و . . .
کتاب در زمان توسعه دات نت 2 نوشته شده. کتاب رایگان و 1150 صفحه است

masoodp666
جمعه 25 مرداد 1387, 16:48 عصر
چنین نیست، زمانی از having استفاده میشه که از Aggregate Function ها در شرطمون استفاده کرده باشیم و استفاده از دستور where اصلا مجاز نیست و باعث ایجاد خطا میشه.منظور من از "نتایج" همان نتایج یک function بود.


به یک نکته هم توجه کنید، بهینه سازی روی هر چیزی جواب نمیده! بهینه سازی زمانی ارزش داره که شما برنامه را با یک Profiler بررسی کنید و بخش هایی از برنامه را که بیشترین ترافیک را دارند، شناسایی کنید، اون وقت روی بهینه کردن این بخش ها تمرکز کنید، وگرنه بهینه کردن کدی که صرفا یک بار اجرا میشه، یا احتمال اجرای آن در طول برنامه بسیار کم هست، ارزش خاصی نداره! اول ممنون از استاد کشاورز و بقیه دوستان که حداقل بنده رو، از تجربیات خودشون بی نصیب نذاشتن. دوم اینکه هدف از ایجاد این تاپیک این بود که تجربیات share بشه و فقط صحبتها پیرامون مباحثی که بنده مطرح میکنم نچرخه اگه دوستان احساس میکنند که جور دیگه ای باید بحث رو پیش برد حتما مطرح کنند.

بهرحال خود بنده سوال دیگه ای داشتم
***ویرایش شده توسط مدیر***

masoodp666
شنبه 26 مرداد 1387, 10:40 صبح
درود و خسته نباشید به آقای مداح
آقای مداح سوال بنده در راستای تاپیک بود و در واقع سوال نبود بلکه ادامه بحث در زمینه بهینه سازی برنامه بود. من نوع بحث تاپیک رو گفتگو انتخاب کردم تا بشه در مورد این بحث گفتگو های زیادی انجام بشه که خوب این خودش میتونه بالطبع سوالهای زیادی رو در بر بگیره.

در نهایت تصمیم گیرنده شما هستید.

ممنون