With respect to memory management, memory is divided into 3 types.
Long memory
Memory compaction
Memory Management
In CLR via C# which is the back bone of my studies related to dot net framework has explained the process of memory management in the following way.
Garbage collector working :
To study these steps we need to understand how Garbage collector works.
How Finalize works ? (~ClassName)
Reference :
Long memory
- Static members are stored.
- No talk of memory management.
- Don't need memory management.
- Data are stored in stack data structure.
- Data are stored in heap data structure.
- Large object heap i.e. > 85 KB doesn't need memory compaction.
- Small object heap i.e. < 85 KB need memory compaction
Memory compaction
- Memory is allocated in different ways.
B1 -10 MB
|
B2 -10 MB
|
B3 -10 MB
|
B4 -20 MB
|
B5 -30 MB
|
B6 40 MB
|
- Consider this memory block. Now block B7 which is of 40 MB wants memory. Memory Management Unit will check for unused memory. B3 and B5 are not used. It will be removed. Now we have 2 memory blocks empty, but B7 doesn't fit into any block.
B1 -10 MB
|
B2 -10 MB
|
Empty -10 MB
|
B4 -20 MB
|
Empty -30 MB
|
B6 40 MB
|
- So memory has to be compacted. The higher memory will be moved upper (lesser memory address) and rearrangement of memory blocks is done. In such case every block will have 2 pointers start and end. Those will be changed. Now we have 40 MB block which is enough for B7.
B1 -10 MB
|
B2 -10 MB
|
B4 -20 MB
|
B6 40 MB
|
Empty -40 MB
|
Memory Management
In CLR via C# which is the back bone of my studies related to dot net framework has explained the process of memory management in the following way.
- Allocate memory for the type that represents the resource (usually accomplished by using
C#’s new operator). - . Initialize the memory to set the initial state of the resource and to make the resource usable.
The type’s instance constructor is responsible for setting this initial state. - Use the resource by accessing the type’s members (repeating as necessary).
- Tear down the state of a resource to clean up.
- Free the memory. The garbage collector is solely responsible for this step.
Garbage collector working :
To study these steps we need to understand how Garbage collector works.
- Garbage collection is a mark and prepare/sweep engine.
- It will collect reachable object graph from roots and will check for reachability. It will only check for reference type variables and will also check in reference locations like thread stack for static references and reachable object in registry object.
- Those which are reachable from root are marked and which are not reachable are not marked.
- Now which are marked are compacted and pushed to down in the heap.
- When compacting, CLR will take care the new address will be referred in the referring location otherwise memory might be corrupted.
- CLR subtracts from each root the number of memory it shifted and will store the new address.
- Most of the out of memory exception happens when Garbage collector is unable to allocate new memory in process memory block because all the memory is reachable.
GC works on generation to improve performance. There are 3
generations available in GC.
- Data are divided as small object heap and large object heap data.
- Heap works as stack w.r.t Garbage collection. As memory is not there in Gen0 then objects are moved to Gen1 then Gen1 to Gen 2.
- All new objects are stored in Generation 0.
- Consider an example where the space in Generation 0 is full and all are reachable. Now a new object request for space, then some of the objects with larger life time will be moved to Generation 1.
- Suppose in above case if some are not reachable, they will be erased and blocks will be compacted and new block will be given memory. (Same as the example explained in memory compaction.)
- Now Generation 0 items are moved to Generation 1 and generation 1 is full. Now garbage collection occurs and survived objects will be moved Generation2.
- Garbage collection occurs only when the generation reaches its maximum limit.
- Only the objects which survive garbage collection will be moved to next generation.
- Generation 2 will be occupied by LOH i.e. large object heap. There is no generation 3 and generation 2 items take more than 2 garbage collections to be removed from memory.
- Every empty object occupies 12 bytes. 4 bytes for object header, 4 bytes for method table or type handler and 4 bytes will be for object which will be empty.
- Every time a new object is called it might call gc.
- When generation reaches threshold, it might call gc.
- Generation algorithm is a cumulative process. Garbage collection on generation 2 applies to Generation 2,1,0. Garbage collection on generation 1 applies to Generation 1,0.Garbage collection on generation 0 applies to Generation 0.
- GC.Collect() may or may not call gc.
- GC.Handle.Pinning() might increase fragmentation.
- You can refer Chapter 21, The Managed heap and Garbage collection of CLR via C#.
Debugging memory :
You can debug whether the data is garbage collected or not
using commands.
Following are the commands you can type in Immediate Window
while debugging to check the status of memory. SOS Debugging Extension is
required to use below commands. You can download Sosex.dll
1.
eeheap –gc :-
Displays information about processed memory consumption
2.
Dumpheap – stat
Displays information about the garbage-collected heap and collection
statistics about objects.
3.
!clrstack
-a Provides the stack trace of managed
code.
4.
!dumparray memory-address Examines
the array elements.
5.
GC.GetGeneration(object) Gives the generation of the given
object.
6.
!objsize memory-address Gets the total size of the object
in the address.
7.
!gcroot memory-address Displays information about roots or
any references for the object specificed.
8.
!finalizequeue – Command to see finalize queue.
Dispose and Finalize :
I have mentioned about some special cases such as database operations,
file operations, windows handle e.t.c. In such cases we need to take care of
freeing memory resources. There are 2 destructors to free resources. They are
dispose and finalize.
Dispose
|
Finalize
|
Deterministic
|
Non
deterministic
|
Explicit
call
|
Implicit
call
|
Asynchronous/Async
|
A-sync
(one thread in clr is reserved for calling finalize for all objects –
Finalizer)
|
One GC
cycle is enough to remove the object
from memory.
|
Min 2 GC
and more than that.
|
How Dispose works ?
- Calling a dispose doesn’t mean the memory is cleared.
- IDispose determines object is disposable or not. Otherwise no use of IDisposable.
- Dispose pattern is used to restrict application from calling multiple dispose.
Dispose example |
How Finalize works ? (~ClassName)
- Finalizer maintains 2 data structure. One is finalize queue and another one is FReachable queue.
- Finalize queue contains the address for the finalize method and the entry is done during new object is created.
- If object is not reachable, it will check for finalize table. If it is present, it will move it to FReachable queue. Since queue takes items one at a time , finalize can take 2 or more than 2 GC cycles.
- Command !finalizequeueis used to see the finalize queue.
Reference :
- CLR via C# 4th edition by Jeffrey Richter
- Operating Concepts by Silberschatz, Galvin, Gagne.
- https://msdn.microsoft.com/en-us/library/bb190764(v=vs.110).aspx
- http://blogs.msdn.com/b/johan/archive/2007/01/11/i-am-getting-outofmemoryexceptions-how-can-i-troubleshoot-this.aspx
- https://msdn.microsoft.com/en-us/library/vstudio/b1yfkh5e%28v=vs.100%29.aspx
No comments:
Post a Comment