PDA

View Full Version : حرفه ای: آزاد سازی فضای حافظه ی Ram



alimooghashang
دوشنبه 26 تیر 1391, 15:58 عصر
سلام
من یه برنامه دارم که الان 200 مگ از حافظه رو مصرف میکنه و بیشتر هم قراره بشه

من داخل برنامه یک UserControl ساختم که با کلیک بر روی یک دکمه اون رو درحالت اجرا new میکنم
ولی وقتی dispose میکنمش چیزی از حافظه ی Ram کم نمیشه!
میخواستم بدونم چطوری باید کنترل ها رو حذف و فضای اشغال شده ی Ram رو آزاد کنم؟
ممنون

fjm11100
دوشنبه 26 تیر 1391, 22:48 عصر
باید یک destructor برای کلاس Usercontrol خودت بنویسی و توش همه چیز را کاملا Dispose کنی.

ali_md110
دوشنبه 26 تیر 1391, 23:10 عصر
اگر از بلاک Using در فراخوانی کلاسها استفاده کنید هم منابه رو آزاد میکنه
کلاهسهایی که اینترفیس IDisposible داخلشون پیاده سازی شده باشه به محض رسیدن به پایان بلاک using منابعشون آزاد میشه
مثل کلاسهای منابع داده

using sqlconnection cnn=new sqlconnection
ولی جهت اطمینان بیشتر ماکروسافت پیشنهاد میکنه کلاسها بصورت دستی درون برنامه dispose بشه

{
}

alimooghashang
دوشنبه 26 تیر 1391, 23:45 عصر
یعنی همه جا از using استفاده کنم؟
ببینید من از dispose هم استفاده کردم و داخل task manager مقدار حافظه ای که اشغال کرده رو دیدم ، چیزی تغیر نمیکرد
تازه زیاد ترم میشد
میشه شمایه پروژه اینطوری درست کنید که داخلش اشیاء ی که ساختید رو آزاد میکنید من ببینم دقیقا باید چطوری این کار رو کرد؟
ممنون

ASKaffash
سه شنبه 27 تیر 1391, 07:14 صبح
سلام
کلا خیلی تاثیر ندارد و GC هر وقت تشخیص دهد نسبت به آزاد سازی منابع اقدام می کند حتی متد Force روی کلاس Static بنام GC هم تست کردم حریف منابع نمی شود (در Help درون MSDN ادعا شده که سریع اشیاء بلامصرف را Dispose می کند ولی واقعا در زمان Force کردن اینکار را انجام نمی دهد) حتما کلاس GC را مطالعه کنید

alimooghashang
سه شنبه 27 تیر 1391, 11:55 صبح
یعنی میگید هیچ راهی نداره؟ و باید این رو به دست سیستم عامل بسپاریم؟

mehdi.mousavi
سه شنبه 27 تیر 1391, 12:33 عصر
یعنی میگید هیچ راهی نداره؟ و باید این رو به دست سیستم عامل بسپاریم؟

سلام.
ابتدا باید بدونید که Managed Heap به دو بخش Small Object Heap و Large Object Heap تقسیم میشه. اگر حافظه مصرفی Object مورد نظر شما، بیش از 85KB باشه، حافظه مورد نیاز از LOH گرفته میشه. بدی LOH این هستش که حافظه پس از آزاد سازی، Compact نمیشه و علیرغم اینکه ممکنه چندین گیگابایت حافظه روی ماشین وجود داشته باشه، با این حال اون حافظه ها "پشت سر هم" (بهش میگن Contiguous) نباشن در نتیجه Memory Allocation موفقیت آمیز نباشه و OutOfMemoryException رخ بده (با اینکه در واقعیت فضای خالی وجود داره، اما بدلیل گسستگی فضا، CLR Heap Manager نمیتوه فضای مورد نیاز رو به برنامه اختصاص بده). بنابراین برنامه نویس باید همواره تمام سعی اش رو کنه که در اکثر مواقع حافظه مورد نظر از SOH گرفته بشه (چرا که بر خلاف LOH، این حافظه Compact میشه). علاوه بر این، GC Handle ها نقش به سزایی رو در میزان حافظه مصرفی بازی می کنن. اگر GC Handle ها (خواسته یا ناخواسته [بدلیل بی اطلاعی برنامه نویس از نحوه عملکرد CLR]) در حافظه Pinned بشن، اونوقت Garbage Collector نمیتونه اونها رو هنگام Collect کردن Move بده، و این مساله منجر به گسستگی حافظه میشه. حالا شما هر چقدر هم از GC بخواهید که حافظه رو Collect کنه، اتفاقی خاصی نمی افته و در عموم موارد نیز، نتیجه عکس میده و با حافظه ای مواجه خواهیم بود که Commit Size اش در حال بیشتر شدنه. از سوی دیگه، استفاده نادرست از Thread ها، تعریف نادرست پارامترها هنگام Call کردن Win32 API ها، استفاده نادرست از COM Object ها و عدم آشنایی با چگونگی کارکرد Interop، استفاده زیاد از متغیرهای static (که باعث Pin شدن حافظه میشن و بطور خودکار در LOH قرار میگیرن) و ... در میزان مصرف حافظه App، نقش دارن.

بنابراین، بعنوان اولین گام، باید Object هایی که استفاده می کنید رو حدالامکان کوچک در نظر بگیرید و اگر IDisposable رو پیاده سازی کرده اند، بدون هیچ درنگی، اونها رو Dispose کنید. متغیرهای static رو به حداقل تعداد ممکن برسونید، به Boxing/Unboxing توجه ویژه ای داشته باشید و هر جا میسره، از Data Structure های Generic استفاده کنید. Connection به دیتابیس رو باز نگه ندارید و به سرعت پس از اجرای Command، اونو آزاد کنید تا به Connection Pool برگرده. Lock های احتمالی در برنامه رو حدالامکان در کوتاه ترین زمان ممکنه آزاد کنید تا بدین شکل، از عدم وجود root مطمئن بشید. Object ها وقتی root داشته باشن، GC نمیتونه اونها رو آزاد کنه و به مرور زمان، حافظه سیستم بواسط App شما از بین میره...

موفق باشید.

fjm11100
سه شنبه 27 تیر 1391, 12:35 عصر
اگر شما چیزی unmanaged داری باید توی مخرب کلاس دستی حذف کنی. می تونی توی متد Dispose هم که توی کد Designer یوزرکنترلت override شده اینکار رابکنی. اما در حالت managed یک کمی از حافظه آزاد نمیشه. البته اگر چندبار new کنی و Dispose میبینی که از حدی بیشتر نمیشه ولی اگر هربار داره زیاد میشه حتما کنترلهایی که توی Usercontrol استفاده کردی نشتی دارند!