Memory Management with .NET Part – 1. BasicGunjan Gandhi
Memory management is a very vast concept and each individual can have different idea or way to implement this in different programming language. In this blog, we are going to see the details of memory management in respect to .NET. Well, .NET is one of the fantastic piece of software engineering. With this framework, user can write their code with no or little knowledge of fundamental. On the other hand difficult topic like memory management are taken care by framework itself, and user can focus on code. As result, many industrial users transfer their skills in .NET Technologies happily and successfully. Due to this kind of support and facilities provided by framework, user can have fantastic knowledge of language, framework classes and can write wonderful applications. Memory management in .NET framework is designed in a such way that user is freed from conscious task of allocation and disposition of memory resources and program is optimized to work best with the most common use of patterns. But actually, this is also the drawback of framework arrangement, as user is unconsciously focused to run application properly instead of making a scalable and performance oriented application. Little to no knowledge of memory management; user will lead them to the performance hell. This “Knowledge gapes” will end up project in load testing failure or failure when project goes live.
In actual scenario, developer never thinks about memory management while writing code and utilizes memory in excess instead of what application needs. Normally in desktop application, we have luxury of memory. But, in web development, excess use of memory at server for session brings a lots of pain. Before moving in memory management detail, first let’s take a look on .NET datatypes and the memory required to store their data.
CTS is one of the component of .NET framework out of many component. CTS has define data types, there behavior, protocol and way of implantation. As per MSDN “The common type system defines how types are declared, used, and managed in the common language runtime, and is also an important part of the runtime’s support for cross-language integration”. CTS works along with CLS (Common language specification). All Data types are segregated in two type, either in Value or Reference type. Following are the list of CTS structure and list of memory requires in bytes.
|CTS Value type list
|C# data type and ref. to CTS. Integer and char type. This types are subset of real number. They are written without decimal component.
Floating point types. This type represent the real number with the decimal component.
|CTS Reference type list
|Reference type are declare or define as per following in C#. It’s depend on operating system also.
As per above, user can identify the size of each data types define in .NET framework. The allocation of memory in value data type are done when declaration is executed, while in reference type, on declaration of variables, memory are not allocated but allocation occurs only when “new” operator is executed. Application runs as process in operating system. So, when new process is created, the runtime reserves a contiguous region of address space for the process. While executing each thread in application, they have their own stack. Contiguous region of address space are called the managed heap. We will look these topics in detail later in blog.
Let’s have example of Data type declaration and its size allocation.
|Value type declaration and its size allocation by executor
Let’s execute this example. When “Main” function is executed and loaded in memory at that time all the memory required by this function are allocated by framework. Means, memory used by variable type are allocated, i.e. 1 byte are allocated to “s” variable and 16 bytes are allocated to “dc” variable. So, finally 61 bytes are allocated to this function.
|Reference type declaration and its size allocation by executor.
In this example, when executor reaches the line no. 12, the Main function definition starting point it only creates space for variable names in memory table. Up to line no. 16 there are no physical memory allocation on stack or in heap. When line 17 executes and executor reaches line no 18, then memory allocation for object is actual done by framework. So, 4/8 bytes are allocated on stack with variable “o”. Now, this variable has starting address of heap allocated to this object. Framework works in similar way for variables “s” and “dt”.
Following is the graphical representation of .NET framework memory allocation process for reference type.
Main Memory crunch allocated by operating system to the process.
After executing line no.17, framework has allocated memory at stack and in heap. Let understand how does it? Framework first allocate memory at stack for variable “o” and at the same time it allocated required memory by objects in heap. Now, once memory allocation done at both side. First memory address of heap are assigned to value of stack address allocated for variable “o”.
.NET framework works similar for all the reference type data type. So, variable type created for String, DataTime, structure type or any other object type (i.e. like DataTable, DataSet, HashTable etc…) memory allocation process works same as described.
Finally, we have seen that how framework works differently in different data type declaration and memory allocation. We need to take care while declaring variable and should follow some pattern (will discuss later). This will help us to lower memory allocation. At the same time, the important point is how you declare, use and deallocate (allocation of memory) variables of reference type. Because, not only declaration portion but deallocation is also important part. Thanks to .NET framework we do not have to deal with the deallocation or releasing of memory. The component which takes care of allocation and deallocation of memories is called GC (Garbage Collector) in framework. But, when user does not know or have little knowledge of memory management it will put burden on this component. We will discuss Memory allocation arrays, delegates, deallocation of memory for reference and value type and how GC work and its behavior in next blog.