Heap و Stack Allocation در C# 🧠💾(بخش دوم)ءGC در NET. برای بهینهسازی پرفورمنس، objectها را به سه نسل تقسیم میکند:
Generational Garbage Collection
🔹️Generation 0:
ءobjectهای کوتاهعمر که معمولاً در methodها تخصیص داده میشوند
🔸️Generation 1:
ءobjectهای با طول عمر متوسط که از collection مربوط به Gen 0 عبور کردهاند
🔹️Generation 2:
ءobjectهای بلندعمر که معمولاً برای دادههای سطح application استفاده میشوند
مثال: نحوهی عملکرد GC
public void GarbageCollectionExample()
{
// Allocated on the heap (Generation 0)
Person p1 = new Person();
}
مثال Generation 0 (GarbageCollectionExample):
ءinstance مربوط به Person با نام p1 روی heap تخصیص داده شده و در Generation 0 آغاز میشود که برای objectهای کوتاهعمر در نظر گرفته شده است.
اگر پس از اتمام method هیچ reference دیگری به p1 وجود نداشته باشد، garbage collector ممکن است آن را در طی collection مربوط به Generation 0 آزاد کند.
public void Generation1Example()
{
List<int> numbers = new List<int>();
for (int i = 0; i < 1000; i++)
{
numbers.Add(i);
}
// 'numbers' will likely survive Gen 0 collection and move to Gen 1.
}
مثال Generation 1 (Generation1Example):
ء<List<int با نام numbers روی heap تخصیص داده میشود. از آنجا که شامل چندین مقدار بوده و برای مدت نسبتاً طولانیتری باقی میماند (برای مثال، تا پایان method)، ممکن است از garbage collection مربوط به Generation 0 عبور کرده و به Generation 1 ارتقاء یابد.
ءGeneration 1 برای objectهایی است که به اندازهی objectهای Generation 0 کوتاهعمر نیستند اما همچنان نیازی به باقیماندن در طول کل عمر application ندارند.
public class CacheManager
{
private static Dictionary<string, string> _cache = new Dictionary<string, string>();
public static void AddItem(string key, string value)
{
_cache[key] = value;
}
}
public void Generation2Example()
{
CacheManager.AddItem("user1", "data1");
CacheManager.AddItem("user2", "data2");
// '_cache' is a static reference and is long-lived, likely residing in Generation 2.
}
مثال Generation 2 (Generation2Example):
کلاس CacheManager از یک Dictionary بهصورت static استفاده میکند، که به این معناست دادههای آن در طول چرخهی عمر application باقی میمانند.
از آنجا که این dictionary (_cache) بلندعمر است، احتمالاً به Generation 2 ارتقاء مییابد که objectهایی را نگهداری میکند که انتظار میرود برای مدت طولانی باقی بمانند؛ مانند cacheها، دادههای static یا objectهای singleton.
مشکلات رایج و Best Practiceها
🔹️Stack Overflow:
زمانی رخ میدهد که تعداد زیادی فراخوانی method تودرتو یا recursion بیش از حد وجود داشته باشد که منجر به اتمام حافظهی stack میشود
🔸️Memory Leaks:
با اینکه NET. دارای GC است، memory leak همچنان میتواند رخ دهد اگر referenceها بهصورت ناخواسته زنده نگه داشته شوند و مانع از جمعآوری آنها توسط GC شوند
Best Practices
🔹️Minimize Long-Lived Objects:
از نگهداشتن referenceها بیش از حد لازم خودداری کنید
🔸️Use Structs Wisely:
تنها زمانی از struct استفاده کنید که type کوچک و کوتاهعمر باشد تا از تخصیص غیرضروری روی heap جلوگیری شود
🔹️Avoid Recursive Calls:
برای recursionهای عمیق، از روشهای iterative استفاده کنید تا از stack overflow جلوگیری شود