Download as pdf or txt
Download as pdf or txt
You are on page 1of 44

Data types and memory

management
Memory
• Each process has its own, separate virtual address space.
• On 32-bit computers, each process has a 2-GB user-mode virtual
address space.
• On 64 bit computer with Windows max virtual address space for the
process is equal to 8 TB
• We work only with virtual address space
• (dev never manipulate physical memory directly)
• The garbage collector allocates and frees virtual memory for you on
the managed heap.
• Virtual memory states:

• Free
• The block of memory has no references to it and is available for allocation.
• Reserved
• The block of memory is available for use, cannot be used for any other
allocation request. Data cannot be stored until this memory block is
committed.
• Committed
• The block of memory is assigned to physical storage.
• Virtual address space can get fragmented.
• You can run out of memory
Value type
• Value types - primitive data types defined by .NET
• Byte • SByte • Int16
• Int32 • Int64 • UInt16
• UInt32 • UInt64 • Single
• Double • Boolean • Char
• Decimal • IntPtr • UIntPtr
• Structs •enumerations
Stored on stack
non self describing type
Value type
• There is no default constructor
• During instantiation all fields are set to either 0 (value type field) or
null (reference type field)

• Can have parameter constructors


• such constructor has to initialize all fields of ValueType
• Cannot be used as base types for other types

• Internally -> System.Object -> System.ValueType -> valueType


System.ValueType
• Overrides virtual methods
• Equals
• GetHashCode
• If performance required -> custom struct should override these
methods
• Equals method by default uses reflection for comparison of two ValueType
instances if it cannot compare fields of VT at bit level
• CLR boxes VT instance and then calls the method on boxed instance of VT
VT – instance copy
• VT instance copy by value into another VT instance
• VT in VT -> copy value
• RT in VT -> copy reference
Reference type
• classes
• interfaces
• delegates
• strings
• instances of "object„

• Stored on heap (SOH / LOH)


• Object reference stored on the stack
• Self describing type
Reference types
• Must be allocated with new operator
Reference type
• Additional information at the level of each allocated object
to deal with:
• GC,
• Synchronization,
• AppDomain identity
• Type information

8 bytes
• Manage pointer –
• the address of the local variable representing value type
• normally used to manage parameter on the stack
• direct address of value type in the memory

• Object reference
• the address of the local variable representing reference type
• reference on the heap
• address + 4 bytes
Reference type layout
• 4 bytes - sync block address
• points to the process-wide table with structures used for synchronization
access to reference types instances
• 4 bytes – address of a memory with Method Table Structure for a
given Reference Type e.g.
• Interface Map Table addresses (AddDomain wide Interface Offset Table)
• Inherited Virtual Method addresses
• Introduced Virtual Method addresses
• Instance Method addresses
• Static Method addresses
Basic memory structure
• Application
• code
• data
• 4 heaps:
• Code Heap – native code instruction after JIT
• Small Object Heap – allocated objects < 85K
• Large Object Heap – allocated object > 85K (with some exceptions)
• Process Heap – low level provided by Windows
Size of object
class MyClass
{
string Test="Hello world Wazzup!";
byte[] data=new byte[86000];
}
Stack
• Tracks the state of an execution thread and all the method calls
• parameters
• local declared variables
• return address
• Stack frame
• Stack up on each other (during consecutive method calls)
• Method call finalization

• Multiple threads
• each thread has its own stack
Boxing / unboxing
• 1 // Integer is created on the Stack
• 2 int stackVariable=12;

• 3 // Integer is created on the Heap = Boxing


• 4 object boxedObject= stackVariable;

• 5 // Unboxing
• 6 int unBoxed=(int)boxedObject;
Another example
• 1 int i=12;
• 2 ArrayList lst=new ArrayList();

• 3 // ArrayList Add method has the following signature


• 4 // int Add(object value)

• 5 lst.Add(i); // Boxing occurs automatically


• 6 int p=(int)lst[0]; // Unboxing occurs
this
• VT
• address of the first instance field of the type’s instance memory
• RT
• address of the Method Table information block of type’s instance memory
Boxing / unboxing
• Call to the Equals / GetHashCode / ToString methods
• requires boxing
• Unless they are overridden
• use standard address of ‘this’ pointer
Garbage collector
• Cleans up unneeded variables allocated on managed heap
• Managed objects automatically get clean content to start with, so their
constructors don't have to initialize every data field.
• Provides memory safety by making sure that an object cannot use the
content of another object.
• Identifies objects that can be reached by the running program

• When memory is released?


• Releases memory before allocation error occurs
• GC can execute at any time
Conditions for GC
• The system has low physical memory
• The memory that's used by allocated objects on the managed heap
surpasses an acceptable threshold
• The GC.Collect method is called
GC roots
• references to objects created by program, memory locations that are always reachable
• object reference by GC roots will survive next garbage collection
• A local variable in a method that is currently running
• lifetime:
• debug – lives to the end of the method call
• release – JIT can analyse the code and find a place in a method after which variable is no longer needed
• static variables – always GC root
• thread static attribute – last as long as thread is running
• managed object passed to unmanaged COM+ library through interop
• becomes GC root with reference count
• once finished reference count == 0 and object can be released
• object has a finalizer
• if it can be released GC detects that there is a finalizer
• move to special GC root area, waits for finalizer method
• usually requires object required more than one garbage collection
GC
• All reachable objects are marked as alive
• If one object references another, anther object is also marked as alive
• Object graph

• Once all alive object are found


• GC releases unused objects
• Compacting (no gaps)
• new objects allocated at the end of heap
GC
• Object can be anchored to more than one roots

• Issues
• Object is referenced by UI component (eg. a table in sub window)
• Object will be free when UI component is updated

• Event handlers -> dev can register methods from objects so the are
executed when given conditions occurs
• Global event handler are newer GC (because the are global), so we have to
remember to unregister methods when actions no longer needed
GC
• Issues
• GC find unreferenced objects
• so unneeded object that is referenced by some other object will stay in the
memory unless it is unreferenced
• Potential for surprising memory leaks (rising memory usage)
Heap fragmentation
• LOH
• objects never moved by the runtime
• LOH fragmentation
• Memory deplection (OutOfMemoryException)
• Spaces between allocated object at LOH
• adds to total memory use at the level of TaskManager for given application
• Windows usually page it out
GC operation modes
• concurrent (workstation)
• .NET try to avoid stop of app execution
• gives the impression to the user that app is responding immediatelly
• synchronous (server)
• suspends running application
Generations
• Recently created object are more likely to by GC
• Works well … until GC.Collect () executed manually
• Object that survives GC are promoted to the next generation

• short living object


• Gen0 – just created never inspected by GC
• medium living objects
• Gen1/Gen2 – inspected by GC 1 / 2 and more times
• long living objects

• Ephemeral generations – 0/1


• Ephemeral segment – each new segment acquired by GC
• when if full GC allocated a new one
Default size of ephemeral segment
• Workstation/server GC 32-bit 64-bit
• Workstation GC 16 MB 256 MB
• Server GC 64 MB 4 GB
• Server GC with > 4 logical CPUs 32 MB 2 GB
• Server GC with > 8 logical CPUs 16 MB 1 GB
GC phaes
• Marking phase
• Relocating phase (update of references to objects that will be moved)
• Compacting phase (moves the objects that survived toward older part of the
segment) – depends on garbage / survivor ratio is high and compaction is needed

• Objects that are promoted to gen2 can be moved to gen2 segment


• gen2 objects might occupy multiple segments

• LOH is not competed unless certain conditions are meet


• hard limit is set
• A memory limit on a container
• The GCHeapHardLimit or GCHeapHardLimitPercent run-time configuration options
GC phases
• Before a garbage collection starts, all managed threads are suspended
except for the thread that triggered the garbage collection
GC Workstation vs GC Server
• Workstation
• designed for client apps
• default for standalone apps
• shorter pauses
• default
• Server
• background apps
• longer pauses
• can be turned on

• Concurrent /background or non – concurrent


Workstation GC: non – concurrent mode
• App thread cannot allocate memory. GC starts
• CLR suspends all managed threads
• CLR collect the garbage in the thread that triggered GC
• CLR resumes all managed threads
Workstation GC concurrent mode
• dedicated high priority thread for GEN2 collection is created

• App thread can’t allocate memory. GC is started


• CLR suspends all managed thread
• calling thread collects Gen0 and Gen1
• CLR starts background collection of Gen2 and resumes all managed threads
• Background threads marks all reachable objects
• stops all managed threads for sweep / compact phase
• CLR resumes managed threads when GC is done
Server GC
• GC happens in dedicated threads: one thread per managed heap
• CLR uses dedicated high priority thread for ephemeral collection
• For background
• set of threads (one per core) for background analysis
• In total on 8 core machine 16 threads
• 8 for ephemeral (1 / core)
• 8 for background (1 / core)
Server GC - background
• Managed thread cannot allocate memory. GC is started
• CLR suspends all managed threads
• Gen0 and Gen1 are collected in dedicated managed threads
(foreground threads)
• CLR suspends GC worker threads. Managed threads are resumed
• Background are called for Gen2 collection.
• Threads mark all reachable objects in memory
• suspend application threads for sweep or compact phase.
• CLR resumes GC worker threads for heap sweep
• App threads are resumed
GC.Collect
• Blocking garbage collection of all generations
• Tries to reclaim maximum amount of available memory

• LOH can be compacted if


• GCSettings.LargeObjectHeapCompactionMode is set to
GCLargeObjectHeapCompactionMode.CompactOnce before calling
GC.Collect()

• GC.Collect(0) – performs GC on 0 gen only


• GC.MaxGeneration - determine the maximum number of generations the system
garbage collector currently supports
• GC.GetGeneration(obj) – determines in which generation obj is stored
• GC.GetTotalMemory(bool) – determines best available approximation of the amount of
memory allocated in managed memory (waits / no wait for GC)
• GC.CollectionCount(int32) – total number of GC run on given gen
• GC.GetAllocatedBytesForCurrentThread - gets the total number of bytes allocated to the
current thread since the beginning of its lifetime
• GetTotalAllocatedBytes(bool precise)
• GC.RegisterForFullGCNotification - Specifies that a garbage collection notification should
be raised
• GC.WaitForFullGCApproach
• GC.WaitForFullGCComplete
GC.KeepAlive
• References specific object and prevents its garbage collection
• Use at the end of the section in which object should not be GC

MyWin32.HandlerRoutine hr = new MyWin32.HandlerRoutine(Handler);


MyWin32.SetConsoleCtrlHandler(hr, true);
//The object hr is not referred to again, such a state can be detected by GC and object can be
released
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Thread.Sleep(30000);
//prevent garbage collection – reference to hr
GC.KeepAlive(hr);
Console.Read();
TryStartNoGCRegion / TryEndNoGCRegion
• Defines the region in which GC should not be executed
• public static bool TryStartNoGCRegion (long totalSize);
• public static bool TryStartNoGCRegion (long totalSize, long lohTotalSize);

• tries to allocated 2*totalSize of memory


• totalSize must be large enough to handle all memory allocation request
within block
• if runtime cannot allocated memory -> runs full GC blocking mode
• returns true if succeded

• Cannot be nested
AddMemoryPressure/RemoveMemoryPressure
• Informs the runtime of a large allocation of unmanaged memory that
should be taken into account when scheduling garbage collection.
• Use in scenarios without IDispose pattern

• Amount of memory declared in AddMemoryPressure should be the


same as amount of memory declared in RemoveMemoryPressure
Weak reference
• Cache mechanism
• Data removed during GC collection

public static WeakReference data;


private static object GetData(){
if (data == null) {
data = new WeakReference(LoadLargeList());
}

if (data.Target == null) {
data.Target = LoadLargeList();
}
return data.Target;
}
GC good practices
• LargeObject – allocate one and reuse

You might also like