مانند قبل، اشیایی که در این مرحله از جمع آوری از نسل صفر باقی ماندند وارد نسل یک میشوند و نیز اشیایی که در این مرحله از نسل یک باقی ماندند وارد نسل دو میشوند. مثل همیشه، بلافاصله نسل صفر از اشیا خالی میشود و اشیای جدید میتوانند در این قسمت قرار گیرند. اشیای موجود در نسل دو اشیای هستند که حداقل دو بار توسط Garbage Collector مورد بررسی قرار گرفته اند. ممکن است بعد از یک یا دو بار جمع آوری نسل صفر، با انجام این عمل در نسل یک مقداری حافظه آزاد شود، اما این عمل تا زمانی که نسل یک به سرحد خود نرسد انجام نمیشود که این کار ممکن است نیاز به چندین بار اجرای جمع آوری در نسل صفر باشد.
Managed heap فقط سه نسل را پشتیبانی میکند: نسل صفر، نسل یک و نسل دو. بنابراین چیزی به نام نسل سه وجود ندارد. زمانی که CLR آغاز به کار میکند، سرحدهایی را برای هر سه نسل در نظر میگیرد. همانطور که پیشتر ذکر شد، سرحد برای نسل صفر حدود 256کیلوبایت است، سرحد برای نسل یک حدودا 2 مگابایت است و سرحد برای نسل دو حدود 10 مگابایت است. بنابراین سرحد نسلها به گونه ای انتخاب شده است که موجب افزایش بازدهی و راندمان برنامه شود. هرچه سرحد یک نسل بیشتر باشد عمل Garbage Collection کمتر روی آن نسل صورت میگیرد. و دوباره، بهبود کارایی به وجود می آید که به دلیل فرضیات اولیه است: اشیای جدید دارای طول عمر کوتاهتری هستند، اشیای قدیمی طول عمر بیشتری دارند.
Garbage Collector موجود در CLR یک جمع آوری کننده با تنظیم کننده خودکار است. این بدین معنا است که Garbage Collector از رفتار برنامه شما می آموزد که چه زمانی باید عمل جمع آوری را انجام دهد. برای مثال اگر برنامه شما اشیای زیادی را ایجاد کند و از آنها برای مدت زمان کوتاهی استفاده کند، این امر ممکن است که آزاد سازی حافظه در نسل صفر مقدار زیادی حافظه را آزاد کند.حتی ممکن است تمام حافظه گرفته شده در نسل صفر آزاد شود.
اگر Garbage Collector مشاهده کند که بعد از انجام جمع آوری نسل یک تعداد محدودی از اشیا باقی ماندند، ممکن است که تصمیم بگیرد که سرحد نسل صفر را از 256 کیلوبایت به 128 کیلوبایت کاهش دهد. این کاهش در فضای معین به این معنی است که عمل جمع آوری باید در فواصل زمانی کوتاه تری رخ دهد اما فضای کمتری را بررسی کند. بنابراین کارهای پروسه شما به صورت قابل توجهی افزایش نمی یابد. اگر تمام اشیای موجود در نسل صفر زباله محسوب شوند دیگر احتیاجی به فشرده سازی حافظه توسط Garbage Collector نیست. این عمل میتواند به سادگی با آوردن اشاره گر NextObjPtr به ابتدای حافظه مورد نظر برای نسل صفر انجام شود. این عمل به سرعت حافظه را آزاد میکند!
نکته:Garbage Collector به بهترین نحو با برنامه های ASP.NET و سرویسهای وب مبتنی بر XML کار میکند. برای برنامه های تحت ASP.NET، یک تقاضا از طرف کلاینت میرسد، یک جعبه از اشیای جدید تشکیل میشود، اشیا کارهای تعیین شده توسط کلاینت را انجام میدهند، و نتیجه به سمت کلاینت بر میگردد. در این مرحله تمام اشیای موجود برای انجام تقاضای کلاینت زباله تلقی میشوند. به بیان دیگر، هر تقاضای برنامه های تحت ASP.NET باعث ایجاد حجم زیادی از زباله میشوند. چون این اشیا اغلب بلافاصله بعد از ایجاد دیگر قابل دسترسی نیستند هر عمل جمع آوری موجب آزاد سازی مقدار زیادی از حافظه میشود. این کار مجموعه کارهای پروسه را بسیار کاهش میدهد بنابراین راندمان Garbage Collector محسوس خواهد بود.
به بیان دیگر، اگر Garbage Collector نسل صفر را مورد بررسی قرار دهد و مشاهده کند که مقدار زیادی از اشیا وارد نسل یک شدند، مقدار زیادی از حافظه توسط Garbage Collection آزاد نمیشود، بنابراین Garbage Collector سرحد نسل صفر را تا 512 کیلوبایت افزایش میدهد. در این مرحله کمتر انجام میشود اما با هر بار انجام این عمل مقدار زیادی حافظه آزاد میشود.
در طول این قسمت چگونگی تغییر دینامیک سرحد نسل صفر شرح داده شد. اما علاوه بر سرحد نسل صفر سرحد نسلهای یک و دو نیز بر اساس همین الگوریتم تغییر میکنند. به این معنی که زمانی که این نسلها مورد عمل جمع آوری قرار میگیرند Garbage Collector بررسی میکند که چه مقدار فضا آزاد شده است و چه مقدار از اشیا به نسل بعد رفته اند. بر اساس نتایج این بررسیها Garbage Collector ممکن است ظرفیت این نسلها را کاهش یا افزایش دهدکه باعث افزایش سرعت اجرای برنامه میشود.
دیگر نتایج کارایی Garbage Collector:
پیشتر در این مقاله الگوریتم کار Garbage Collector شرح داده شد. با این وجود در طول این توضیحات یک فرض بزرگ صورت گرفته بود: اینکه فقط یک ترد در حال اجرا است. اما در مدل واقعی چندین ترد به managed heap دسترسی دارند و یا حداقل اشیای قرار گرفته در managed heap رو تغییر میدهند. زمانی که یک ترد موجب اجرای عمل جمع آوری توسط Garbage Collector میشود، دیگر تردها حق دسترسی به اشیای موجود در managed heap را ندارند(این مورد شامل ارجاعهای اشیای موجود در stack هم میشود) زیرا Garbage Collector ممکن است مکان این اشیا را تغییر دهد.
بنابراین وقتی Garbage Collector بخواهد عمل جمع آوری را آغاز کند، تمام تردهایی که در حال اجرای کدهای مدیریت شده هستند به حال تعلیق در می آیند.CLR دارای چندین مکانیسم نسبتا" متفاوت است که میتواند تردها را به حالت تعلیق در آورد بنابراین عمل جمع آوری میتواند به درستی اجرا شود. دلیل اینکه CLR از چندین مکانیسم استفاده میکند به حالت اجرا نگاه داشتن تردها تا حداکثر زمان ممکن و کاهش سربار کردن آنها در حافظه تا حداقل زمان ممکن است. تشریح این مکانیسمها از اهداف این مقاله خارج است اما تا این حد لازم است ذکر شود که مایکروسافت فعالیتهای زیادی را برای کاهش فشار پردازشی ناشی از Garbage Collector انجام داده است. و نیز این مکانیسمها به سرعت در حال تغییر هستند تا به بهترین کارایی خود برسند.
زمانی که CLR میخواهد Garbage Collector را اجرا کند، ابتدا تمام تردها در پروسه جاری را که در حال اجرای کدهای مدیریت شده هستند به حال تعلیق در می آورد. سپس CLR برای تعیین موقعیت هر ترد تمام اشاره گرهای دستورات در حال اجرا توسط تردها را بررسی میکند. سپس برای تعین اینکه چه کدی توسط ترد در حال اجرا بوده آدرس اشاره گر دستور با جدول ایجاد شده توسط کامپایلر JIT مقایسه میشود.
اگر دستور درحال اجرا توسط ترد در یک آفست مشخص شده به وسیله جدول مذکور باشد گفته میشود که ترد به یک نقطه امن دسترسی دارد. یک نقطه امن نقطه ای است که در آنجا میتوان بدون هیچ مشکلی ترد را به حال تعلیق در آورد تا Garbage Collector کار خود را آغاز کند.اگر اشاره گر دستور در حال اجرای ترد در روی یک آفست مشخص شده توسط جدول درونی تابع قرار نداشت، بنابراین ترد در یک نقطه امن قرار ندارد و CLR نمیتواند Garbage Collector را اجرا کند. در این حالتCLR ترد را هایجک میکند: به این معنی که CLR استک مربوط به ترد را به گونه ای تغییر میدهد که آدرس بازگشت به یک تابع خاص پیاده سازی شده درون CLR اشاره کند. سپس ترد به ادامه کار خود بازمیگردد. زمانی که متد در حال اجرا توسط ترد ادامه پیدا کند، این تابع ویژه اجرا خواهد شد و ترد به حالت تعلق درخواهدآمد.
با وجود این ممکن است در بعضی مواقع ترد از متد خود بازنگردد. بنابراین زمانی که ترد به اجرای خود ادامه میدهد، CLR 250میلی ثانیه صبر میکند. سپس دوباره بررسی میکند که آیا ترد به یک نقطه امن طبق جدول JIT رسیده است یا نه. اگر ترد به یک نقطه امن رسیده بود CLR ترد را به حالت تعلیق درمی آورد و Garbage Collector را اجرا میکند در غیر این صورت مجددا سعی میکند با تغییر Stack مربوط به ترد اجرای آن را به تابع دیگری انتقال دهد در صورت شکست مجددا CLR برای چند میلی ثانیه دیگر نیز صبر میکند. زمانی که تمام تردها به یک نقطه امن رسیدند یا اینکه با موفقیت هایجک شدند، Garbage Collector میتواند کار خود را آغاز کند. زمانی که عمل جمع آوری انجام شد تمام تردها به وضعیت قبلی خود برمیگردند و اجرای برنامه ادامه پیدا میکند. تردهای هایجک شده هم به متدهای اولیه خود بازمیگردند.

نکته: این الگوریتم یک پیچ خوردگی کوچک دارد. اگر CLR یک ترد را به حالت تعویق درآورد و دریابد که ترد در حال اجرای یک کد مدیریت نشده بود آدرس بازگشت ترد هایجک میشود و به ترد اجازه داده میشود که به اجرای خود ادامه دهد. با این وجود در این حالت به Garbage Collector اجازه داده میشود که اجرا شود در حالی که ترد مذکور در حال اجرا است. این مورد هیچ اشکالی را به وجود نمی آورد زیرا کدهای مدیریت نشده به اشیای موجود در managed heap دسترسی ندارندتا زمانی که آن اشیا پین شوند. یک شیی پین شده شی است که Garbage Collector حق حرکت دادن آن را در managed heap ندارد. اگر تردی که در حال حاضر در حال اجرای یک کد مدیریت نشده بود، شروع به اجرای یک کد مدیریت شده کند، ترد هایجک میشود و به حالت تعلیق درمی آید تا زمانی که Garbage Collection به درستی به اتمام برسد.

علاوه بر مکانیسمهای ذکر شده(نسلها، نقاط امن، و هایجک کردن)، Garbage Collector از بعضی از مکانیسمهای اضافی دیگری نیز استفاده میکند که باعث افزایش بازدهی آن میشود.
اشیای بزرگ:
فقط یک نکته قابل ذکر دیگر که باعث افزایش سرعت و بازدهی بهتر میشود باقی مانده است. هر شیی که 85000 بایت یا بیشتر فضای حافظه را اشغال کند یک شیی بزرگ در نظر گرفته میشود. اشیای بزرگ در یک heap ویژه اشیای بزرگ قرار میگیرند. اشیای درون این heap مانند اشیای کوچک (که راجع به آنها صحبت شد) finalize و آزاد میشوند. با این وجود این اشیا هیچ وقت تحت فشرده سازی قرار نمیگیرند زیرا شیفت دادن 85000 بایت بلاک حافظه درون heap مقدار زیادی از زمان CPU را هدر میدهد.
اشیای بزرگ همواره به عنوان نسل دو در نظر گرفته میشوند، بنابراین این اشیا باید فقط برای منابعی که مدت زمان زیادی در حافظه می مانند ایجاد شوند. تخصیص اشیایی که دارای طول عمر کوتاه هستند در قسمت اشیای بزرگ باعث میشود که عمل جمع آوری نسل دو سریعتر انجام شود و این مورد نیز به بازدهی و کارایی برنامه صدمه وارد میکند.