ممنون استاد علی
الان من متوجه نشدم
الان منظورتون اینه که بعد از بلاک ، متغییرحذف میشه ولی اشاره گرش باقی میمونه؟
اگه خود متغییره حدف بشه بعد از بلاک ، دیگه اشاره گر توی چی باقی میمونه؟!!
اشاره گرش هم باید حذف بشه دیگه!
یا اینکه منظورتون اینه که بعد از بلاک ، متغییر و اشاره گرش با هم حذف میشن؟
متغیر ئه همون اشاره گر ئه دیگه، ذاتا Pointer ئه. مقدار اشاره گر در حافظه متغیر بوده، وقتی متغیری در کار نیست، اشاره گرش کجای حافظه بمونه؟ متغیری که به یک شی اشاره می کنه یک اشاره گر ئه، مقدارش یک آدرس حافظه است. به یک آدرس حافظه اشاره می کنه که نقطه آغاز داده های مربوط به شیء ئه. وقتی متغیر حذف بشه، مقدارش که یک آدرس حافظه است هم حذف شده، شی نه ها، اشاره گرش. شیء فعلا سر جاش در حافظه است. در نتیجه یکی از تعداد ارجاع هایی که به شی ء بوده کم میشه، GC آمار این ارجاع ها رو داره. که هر وقت این تعداد ارجاع ها به صفر برسه و دیگه ارجاعی به شیء مورد نظر نمونه، اون شیء بعد از این قابل دسترسی نیست، پس GC از اون لحظه به بعد مجوز داره به عنوان یک شیء بلامصرف حافظه شو آزاد کنه.
اگه این طوره ، پس چرا در کد زیر :
کد:
using (System.IO.StreamReader file = new System.IO.StreamReader(@"F:\Film\TV\Serial\Istadeh Dar Ghobar\058-istadeh-dar-ghobar-ghesmat-5.mp4"))
{
string a = file.ReadToEnd();
}
GC.Collect();
وقتی متغییر a را null نکردم ، و بعد که GC.Collect() فراخونی شد ، شی a را آزاد نکرد؟ فقط وقتی آزاد میکنه که شی a را null کنم
شیء ای که در حافظه است و مقدار رشته a داخلش ذخیره شده کاملا مستقل از متغیر a ئه. a عملا مقداری که نگه داشته یک آدرس حافظه است، a یک اشاره گر ئه، شیء اش جدا است. شاید برای string مثال خوبی نباشه اما ممکنه چندین ارجاع به یک شیء باشه که با حذف شدن a هنوز ارجاعی مونده باشه. GC نمیاد برای یک متغیر a روتین بررسی راه بندازه. GC که همون لحظه که از بلاک using در میایید که نمیاد چک کنه خوب حالا چند تا ارجاع به شیء متغیر های داخل using مونده که دوان دوان بره آزاد شون کنه. این اصلا الگوریتم بهینه ای نیست، تعداد بلاک هایی که فقط واسه اجرا شدن یک برنامه ساده در حد Hello World اجرا میشه خیلی زیاده، GC اگه بخواد سر هر بلاک همچین بررسی ای رو انجام بده که نصف وقت پردازنده رو باید اختصاص بدن به GC. شما وقتی میگید GC.Collect معنی اش این نیست که هر چی ارجاع هست برو چک کن ببین شیء شون آزاد کردنی هست یا نه، معنی اش اینه که هر چی شیء رو تا این لحظه به عنوان بلااستفاده شناسایی کردی آزاد کن. مطالب قبلی رو بگردید می بینید که چند بار تکرار کردم که GC.Collect یک درخواست ئه، خواهش ئه، GC مستقل ئه و مستقل کار می کنه، از شما دستور نمی گیره. فرق ئه بین این که بگم "
فردا میام" یا بگم "
سعی می کنم فردا بیام". در خود MSDN هم گفته با GC.Collect ئه
try می کنید،
سعی می کنید، تعداد اشیاء در حافظه بیشتر از اونی ئه که بررسی تک تک شون موثر باشه و ارزش داشته باشه.
Use this method to try to reclaim all memory that is inaccessible. It performs a blocking garbage collection of all generations.
پس کلا به ساختار متد ReadToEnd برمیگرده که داخلش چه حافظه و متغییرهایی گرفته شد
فقط اون نیست، همون نوع داده string هم تاثیر داره. تبدیل byte به string خودش روتین مبدل میخواد. a که نمیتونه به یک []byte اشاره کنه. به string اشاره می کنه، پس باید تبدیل داده صورت بگیره.
الان پس ویژال استودیو بیشتر از 2 گیگ نمیتونه استفاده کنه
نه فقط Visual Studio، هیچ پروسه 32 بیتی ای نمیتونه. البته اگه لازم باشه میتونه با چندین پروسه کار کنه و یک حافظه ای رو هم برای استفاده اشتراکی همه نسخه هاش قرار بده که با هم تبادل داده کنند. ممکنه یک برنامه برای اجرای موازی یک روتینی چندین پروسه از خودش رو اجرا کنه.
اما زامارین برای خودش جدا کار میکنه (هر چند در ویژال استودیو هست) . درسته؟
در ویژوال استدیو بودنش رو مطمئن نیستم چون تا حالا بررسی نکردم نحوه اجرا شدن چطوریه اما اگه جزئی از پروسه اصلی ویژوال استدیو باشه نمیتونه حافظه اضافه ای داشته باشه که از محدوده 2GB ئه پروسه فراتر بره.
آخه یه بار با زامارین کار میکردم اگه درست به ذهنم برسه ، 5 گیگ فضا اشغال کرده بود و یحتمل باید 64 بیتی باشه
اگه 64 بیتی باشه که قطعا پروسه جدایی ئه، حتی اگه 5 مگابایت حافظه هم مصرف کنه نمیتونه جزئی از یک پروسه 32 بیتی باشه.
حالا منظورم اینه که برنامه ی 32 بیتی میتونه همون قدر از پردازنده کار بکشه که برنامه ی 64 بیتی میتونه؟ یعنی برنامه ای چون 32 بیتی هست ، امکان داره که نتونه بخاطر 32 بیتی بودن اش از تمام قدرت پردازنده استفاده کنه؟ یا اینکه برنامه های 64 بیتی ، در پردازنده ، سریعتر از برنامه های 32 بیتی پردازش میشن یا اینکه فرقی ندارن؟
تا اونجایی که به معماری پردازنده های مرسوم و سیستم عامل ویندوز مربوطه نمیتونه، یعنی کارایی کد 32 بیتی نمیتونه به اندازه 64 بیتی باشه. صحبت حداکثر حافظه در اختیارش نیست ها، برای سازگاری با پردازنده و محیط اجرای 64 بیتی سربار بهش تحمیل میشه، چه سخت افزاری و چه نرم افزاری. اجرای کد 32 بیتی برای پردازنده 64 بیتی به تنهایی سربار داره، چون از نظر هزینه به صرفه نیست که بیان یک پردازنده رو از ترکیب دو بخش کاملا مستقل 32 بیتی و 64 بیتی بسازند، اقتصادی نیست، بخش 32 بیتی رو با شبیه سازی و تطبیق با محیط 64 بیتی پیاده سازی می کنند. و تطابق اون کد 32 بیتی با پردازنده ای که مدارش ذاتا 64 بیتی ئه سربار ایجاد می کنه، یعنی کارایی کمتر. این تازه بخش سخت افزاری اش بود. در کنارش بحث نرم افزاری مطرحه، ویندوز نمیتونه در محیط 64 بیتی که آدرس ها 64 بیتی اند یک پروسه 32 بیتی رو مستقیم اجرا کنه، از شبیه ساز استفاده می کنه که باز سربار داره.
اما در حالت کلی اصلا حداکثر قدرت پردازنده بدست نمیاد که، یک آمار کلی و حدودی از میزان کارایی پردازنده سیستم تون بگیرید، میبینید که بیشتر وقتش بیکار ئه. این یک معضل جدید نیست، از همون سیستم عامل های ابتدایی همین مساله بوده که پردازنده بیشتر بیکار ئه تا مشغول. معنی اش چیه؟ معنی اش اینه که اگه بشینید کد همه برنامه های روی ویندوز تون رو بازنویسی و بهینه کنید تا بهتر از پردازنده استفاده کنند، نتیجه اش بیکار شدن بیشتر پردازنده است، چون کارشون زودتر تموم میشه. و این هم چیز بدی نیست که بخواهید جلوشو بگیرید.
اون چیزی که شما میخواهید بهش برسید، واقعا اون چیزی نیست که مطلوب ئه. شما باید سعی کنید الگوریتمی پیدا کنید که سریعتر به جواب برسه، یعنی زودتر پردازنده رو بیکار کنه، کمتر وقت پردازنده رو بگیره و پردازنده بیکار تر بشه. نه اینکه طوری از پردازنده کار بکشید که بیشتر اشغال بشه. بیشتر اشغال شدن پردازنده به معنی کارایی بهتر کد شما نیست، کد شما میخواد یک کاری انجام بده، نه اینکه حرارت و توان مصرفی پردازنده رو ببره بالاتر. این مثل اینه که بگیم چطور کار کنیم که بیشتر خسته بشیم. بیشتر خسته شدن به این معنی نیست که بهتر کار می کنیم.