| marp | true |
|---|---|
| theme | minimal |
| paginate | true |
| header | .NET Garbage Collection |
| footer | Maximilian Meffert (c) 2020 |
Writing High-Perforamnce .NET Code by Ben Watson
In .NET, you need to think of memory performance at least as much as CPU performance. It is so fundamental to smooth .NET operation, that the most significant chunk of this book’s content is dedicated to just this topic. - Ben Watson, Writing High-Perforamnce .NET Code
Heap = Process memory reserved for allocation of data.
A mangaged process has 2 kinds of heaps:
-
Native Heap: used by Windows and CLR for unmanaged memory, e.g. Windows API, OS data structures, the CLR itself
-
Managed Heap (GC Heap): used by the CLR to allocate objects subjected to garbage collection
The Managed Heap is devided in 2 sections.
-
Small Object Heap (SOH) for objects < 85000 bytes, most of all objects
-
Large Object Heap (LOH) for objects >= 85000 bytes, mostly arrays and strings
Size of an object without fields and methods: 16 bytes (32-bit), 32 bytes (64-bit). Actually its 12 bytes and 24 bytes but the memory manager can't handle that very well.
The Small Object Heap is divided into 3 sections called generations.
- Gen 0 the 1st genertaion
- Gen 1 the 2nd generation (serves as cache for Gen 2)
- Gen 2 the 3rd and last generation
Objects may pass through all generations during their lifetime.
Once in Gen 2, objects stay here till they die.
Objects are alive as long as they are referenced by a GC root, e.g. static variables, managed threads or pinned handles.
Segments = Fixed sized parts of physical memory owned by SOH or LOH.
- LOH and Gen 2 can span multiple segements
- Gen 0 and Gen 1 always reside in the same segment
The CLR tries to allocate new objects 3 times:
- Try to allocate at the end of Gen 0
- Try to allocate anywhere within Gen 0
- Or try to expand Gen 0 and allocate at the new end
If expansion exceeds segement size a Garbage Collection is triggered!
Garbage Collection consists of 4 phases:
- Suspension: Suspend all managed threads
- Mark: Mark all objects referenced by any GC root as seen, i.e. alive
- Compact: Relocate and promote seen objects to reduce memory fragmentation
- Resume: Resume all suspended threads
Garbage Collection happens only for the triggering generation and lower generations. Gen 2 collection also collects Gen 1 and Gen 0. Gen 1 collection also collects Gen 0.
All non-seen objects die of here!
- Trying to allocate obj6 triggers a garbage collection, i.e.:
- Fast Allocation has faild
- and Gen 0 expansion exceeds segement size
- A Gen0 Garbage Collection is triggered:
- Gen 1 objects are not moved and promoted to Gen 2 (see Gen 1 as cache for Gen 2)
- Gen 0 objects are moved to a new segement and promoted to Gen 1
- A new Gen 0 is reserved and obj6 is allocated there
- Gen 2 and Gen 1 are not garbage collected!
Gen 2 and Gen 1 collections may not be triggered by allocations but due to other internal GC metrics and thresholds, e.g. available memory on a machine.
[...] the garbage collector was explicitly designed with this idea in mind: Collect objects in Gen 0 or not at all. - Ben Watson, Writing High-Perforamnce .NET Code
- Garbage Collections tend to get more expensive for higher generations
- Gen 1 objects need to be moved physically when SOH requires a new segement
Ideally, most objects die in Gen 0 and few live in Gen 2 for the lifetime of the application.
