middotnet-runtime
GC automatically frees memory. 3 generations: Gen0 (short-lived), Gen1 (buffer), Gen2 (long-lived). Plus LOH for objects > 85KB.
Gen0: new objects, collected frequently and fast. Gen1: survived Gen0, intermediate buffer. Gen2: long-lived objects (singletons, caches), collection is expensive (full GC). LOH (Large Object Heap): objects > 85KB, collected with Gen2, not compacted by default. Workstation GC: optimized for latency. Server GC: for throughput (one heap per CPU core).
// Проверить GC stats
var info = GC.GetGCMemoryInfo();
Console.WriteLine($"Gen0: {GC.CollectionCount(0)}");
Console.WriteLine($"Gen1: {GC.CollectionCount(1)}");
Console.WriteLine($"Gen2: {GC.CollectionCount(2)}");
Console.WriteLine($"Heap: {GC.GetTotalMemory(false) / 1024}KB");
// Настройка в csproj
// <ServerGarbageCollection>true</ServerGarbageCollection>
// <ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>When yes
Understanding GC is essential for diagnosing memory pressure, high latency spikes, LOH fragmentation
When no
Don't optimize GC until you've measured — premature optimization
Interview tip
Gen2 collection = stop-the-world (in non-concurrent mode). Frequent Gen2 collections are a sign of memory pressure.