Memory Models in
C#
Sophie Obomighie
C# Programmer approx. 1 year
IT support
……
Lagos, Nigeria
What to expect from this talk
1. Meaning of Memory Models (Context)
2. Stack and heap
3. Value types and reference types
4. Compilation
a. HOW A COMPILER WORKS
b. THE COMPILATION PROCESS
i. Lexical Analysis
ii. Parsing
iii. Semantic Analysis
iv. Optimization
v. Code Generation
Disclaimer : High Level conversation based on study and a little practise. Not an expert.
Learning solid, Introduce the topic.
CLR
- Common Language Runtime
- Runtime environment for .NET
- runs the code
- Download .NET (Linux, macOS, and Windows)
(microsoft.com)
- Story - 36 bit system installation of runtime in place of SDK.
HOW A COMPILER
WORKS
- a program that reads the code you write and generates
something that the runtime engine can execute
- Interpreter, command, JIT
- different languages, byte code, intermediate language
(MSIL),
- portability – compiler for different platforms (Windows 32-
bit, 64-bit, Mac, Linux, etc.) without having to change the
code.
- expose the common language runtime's functionality
- So that code benefits from managed execution
environment.
HOW A COMPILER
WORKS
- Code developed with a language compiler that targets the runtime is called
managed code.
- Managed Code has adv. - cross-language integration, cross-language
exception handling, enhanced security, versioning and deployment support, a
simplified model for component interaction, and debugging and profiling
services.
- Compilers produce output
- CLR consumes/Process
- Why ? type system, format of metadata, and the run-time environment (the
virtual execution system) are all defined by a public standard, the ECMA
Common Language Infrastructure specification.
HOW A COMPILER WORKS
- Metadata from compiler describes the types, members, and references in your code.
- Metadata stored with the code in the common language runtime portable executable (PE) file
- runtime uses metadata to locate and load classes, lay out instances in memory, resolve method
invocations, generate native code, enforce security, and set run-time context boundaries.
- runtime automatically handles object layout and manages references to objects, releasing
them when they are no longer being used.
- Objects written in different languages can communicate with each other, and their behaviors
can be tightly integrated.
- For example, you can define a class and then use a different language to derive a class from
your original class or call a method on the original class. possible because language compilers
and tools that target the runtime use a common type system defined by the runtime, and they
follow the runtime's rules for defining new types, as well as for creating, using, persisting, and
binding to types.
- Benefits of runtime : Performance improvements, Cross Language feature utilization, Support
for multithreaded, scalable applications, structured exception handling, custom attributes,
Garbage collection.
Memory Models
● allows a compiler to perform many important optimizations.
● Multi threading
● Designing a memory model that allows a maximal degree of freedom for compiler optimizations
while still giving sufficient guarantees about race-containing programs.
● changes to the values of shared variables only need to be made visible to other threads when such a
synchronization barrier is reached.
● These semantics then give optimizing compilers a higher degree of freedom when applying
optimizations:
● needs to make sure only that the values of (potentially shared) variables at synchronization barriers
are guaranteed to be the same in both the optimized and unoptimized code. In particular,
reordering statements in a block of code that contains no synchronization barrier is assumed to be
safe by the compiler.
Stack and Heap
- Stack and heap are portions of the memory. The Common Language Runtime (CLR) allocates
memory for objects in these parts.
- Stack is a simple LIFO(last-in-first-out) structure.
- Variables allocated on the stack are stored directly to the memory and access to this memory is
very fast, and its allocation is done when the program is compiled.
- Method Invocation - > CLR bookmarks the top of the stack - > method pushes data onto the stack
as it executes - > method completes -> CLR resets the stack to its previous bookmark.
- Value type variables are stored in the stack
- A stack is a way to store program data and is a per thread process. The stack is very fast and is used
for value types.
- Heap allows objects to be allocated or deallocated in a random order.
- Variables allocated on the heap have their memory allocated at run time and accessing this
memory is a bit slower, but the heap size is only limited by the size of virtual memory.
- The heap requires the overhead of a garbage collector to keep things in order.
- reference type variables are stored in the heap. And is a per-application process
Stack and heap
https://medium.com/c-programming/c-memory-management-part-1-c03741c24e4b
Garbage Collection
- process of cleaning up the heap.
- managed languages such as C# as well as dynamic languages such as Ruby
- in Objective-C, you allocate memory as you need and specify pointers vs value types explicitly.
When you’re done with the variable, you deallocate it yourself.
- Determining what objects and memory are subject to collection requires overhead and can slow
things down – It’s undecidable will a process ever be complete, therefore it’s not possible to know if
memory will ever not be needed
- reducing the memory size of the heap
- Tracing is the most widely used method of garbage collection.
- As program runs, the garbage collector will take a look at a set of “root” objects and their
references, and trace those references through the stack.
- As the trace runs, the GC will identify objects that are not traceable which are then deallocated
and the memory freed.
Garbage Collection
- If objects aren’t referenced they are targeted for deallocation
- Disadvantages : When will the GC get around to executing? –
- implementing various flavors of generational (or ephemeral) implementations.
Value types and reference
types
A variable can store a value of a certain type.
The data types can be divided into value type and reference type.
The differentiation between value type and reference type depends on two features.
Those are where the variables are stored in memory and how they behave with an assignment statement.
The key difference between the value type and reference type is that a value type holds a data value
within its own memory space while a reference type holds a pointer to another memory location that
holds the data.
Value types => bool, byte, char, decimal, double, float, int, long, uint, ulong, ushort, enum, struct
A reference type contains a pointer to another memory location that holds the real data.
Reference types => class, interface, delegate, string, object, dynamic, arrays
If you assign a value type variable to another variable, the value is copied directly.
Value types and reference
types
The value types can be divided into two categories.
They are predefined types and user-defined types.
The predefined types are provided by the programming language.
The user can also create value types. Two such user-defined value types are structure and enumerations.
Value types and reference
types
Finalizer & Dispose
- when we create objects that include unmanaged resources such as windows, files, network and
database connections, we must explicitly release those resources after using them in our
applications. This can be done by using finalizers, implementing Dispose method from the
IDisposable interface.
What is a finalizer?
Finalizers (which are also called destructors) are used to perform any necessary final clean-up when a
class instance is being collected by the garbage collector. Some important points about finalizers are:
A class can have only one finalizer, A finalizer does not have modifiers or parameters, Finalizers cannot be
called explicitly, they are called by the garbage collector (GC) when the GC considers the object eligible
for finalization. They are also called when the program finishes in .NET framework applications.
Dispose Method
If our application uses an expensive external resource, we should then release the resource explicitly. We
can do this by implementing Dispose method from IDisposable interface. By this way, we can improve
the performance of our application as well.
THE COMPILATION
PROCESS
i. Lexical Analysis
ii. Parsing
iii. Semantic Analysis
iv. Optimization
v. Code Generation
Lexical Analysis
Lexical Analysis simply analyzes the code that’s passed to the compiler and splits it into tokens.
The program within the compiler that does this is called the lexer. So, using our code sample, the lexer
will generate these pseudocode tokens (using tuples):
The thing being analyzed by the lexer is the lexeme. A token is what’s produced from this analysis.
Parsing
After the lexer has tokenized the incoming code string, the parser takes over,
applying the tokens to the rules of the language – also known as a formalized
grammar.
parse their meaning and, essentially, what they’re supposed to mean. A parser
analyzes the tokens and figures out the implicit structure:
Semantic
Analysis
Lexical
Scoping
Semantic Analysis is where
the compiler tries to figure
out what you’re trying to do.
Optimization
the longest.
little tweaks to make your code smaller, faster, and use less memory and power
(which is important if you’re writing code for phones)
Code Generation
- package it up
- will compile code text files into an intermediate structure, which will be
further compiled later on.
- compiles into an actual second language called IL (or MSIL).
- Just In Time
CREDITS: This presentation template was
created by Slidesgo, including icons by
Flaticon,and infographics & images by Freepik
Thanks!
sophieobomighie@outlook.com
● https://bigmachine.io/products/the-imposters-handbook/
● https://www.liquisearch.com/memory_model_programming/history_and_significance
● https://medium.com/c-programming/c-memory-management-part-1-c03741c24e4b
● https://www.differencebetween.com/difference-between-value-type-and-vs-reference-
type/#:~:text=What%20is%20the%20Difference%20Between%20Value%20Type%20and,%20Stored%20Location%20
%203%20more%20rows%20
● http://computer-programming-forum.com/4-csharp/eca1cac70ad2f910.htm
● https://docs.microsoft.com/en-us/dotnet/standard/clr
● https://www.youtube.com/watch?v=clOUdVDDzIM
● http://joeduffyblog.com/2007/11/10/clr-20-memory-model/
● https://medium.com/c-programming/c-memory-management-part-2-finalizer-dispose-d3b3e43c08d1
● https://medium.com/c-programming/c-memory-management-part-3-garbage-collection-18faf118cbf1
● https://www.youtube.com/watch?v=-JOkkn1ET8c
● https://www.youtube.com/watch?v=9FEfy9y0fFQ
● https://www.youtube.com/watch?v=clOUdVDDzIM
Resources

Memory models in c#

  • 1.
    Memory Models in C# SophieObomighie C# Programmer approx. 1 year IT support …… Lagos, Nigeria
  • 2.
    What to expectfrom this talk 1. Meaning of Memory Models (Context) 2. Stack and heap 3. Value types and reference types 4. Compilation a. HOW A COMPILER WORKS b. THE COMPILATION PROCESS i. Lexical Analysis ii. Parsing iii. Semantic Analysis iv. Optimization v. Code Generation Disclaimer : High Level conversation based on study and a little practise. Not an expert. Learning solid, Introduce the topic.
  • 3.
    CLR - Common LanguageRuntime - Runtime environment for .NET - runs the code - Download .NET (Linux, macOS, and Windows) (microsoft.com) - Story - 36 bit system installation of runtime in place of SDK.
  • 4.
    HOW A COMPILER WORKS -a program that reads the code you write and generates something that the runtime engine can execute - Interpreter, command, JIT - different languages, byte code, intermediate language (MSIL), - portability – compiler for different platforms (Windows 32- bit, 64-bit, Mac, Linux, etc.) without having to change the code. - expose the common language runtime's functionality - So that code benefits from managed execution environment.
  • 5.
    HOW A COMPILER WORKS -Code developed with a language compiler that targets the runtime is called managed code. - Managed Code has adv. - cross-language integration, cross-language exception handling, enhanced security, versioning and deployment support, a simplified model for component interaction, and debugging and profiling services. - Compilers produce output - CLR consumes/Process - Why ? type system, format of metadata, and the run-time environment (the virtual execution system) are all defined by a public standard, the ECMA Common Language Infrastructure specification.
  • 6.
    HOW A COMPILERWORKS - Metadata from compiler describes the types, members, and references in your code. - Metadata stored with the code in the common language runtime portable executable (PE) file - runtime uses metadata to locate and load classes, lay out instances in memory, resolve method invocations, generate native code, enforce security, and set run-time context boundaries. - runtime automatically handles object layout and manages references to objects, releasing them when they are no longer being used. - Objects written in different languages can communicate with each other, and their behaviors can be tightly integrated. - For example, you can define a class and then use a different language to derive a class from your original class or call a method on the original class. possible because language compilers and tools that target the runtime use a common type system defined by the runtime, and they follow the runtime's rules for defining new types, as well as for creating, using, persisting, and binding to types. - Benefits of runtime : Performance improvements, Cross Language feature utilization, Support for multithreaded, scalable applications, structured exception handling, custom attributes, Garbage collection.
  • 7.
    Memory Models ● allowsa compiler to perform many important optimizations. ● Multi threading ● Designing a memory model that allows a maximal degree of freedom for compiler optimizations while still giving sufficient guarantees about race-containing programs. ● changes to the values of shared variables only need to be made visible to other threads when such a synchronization barrier is reached. ● These semantics then give optimizing compilers a higher degree of freedom when applying optimizations: ● needs to make sure only that the values of (potentially shared) variables at synchronization barriers are guaranteed to be the same in both the optimized and unoptimized code. In particular, reordering statements in a block of code that contains no synchronization barrier is assumed to be safe by the compiler.
  • 8.
    Stack and Heap -Stack and heap are portions of the memory. The Common Language Runtime (CLR) allocates memory for objects in these parts. - Stack is a simple LIFO(last-in-first-out) structure. - Variables allocated on the stack are stored directly to the memory and access to this memory is very fast, and its allocation is done when the program is compiled. - Method Invocation - > CLR bookmarks the top of the stack - > method pushes data onto the stack as it executes - > method completes -> CLR resets the stack to its previous bookmark. - Value type variables are stored in the stack - A stack is a way to store program data and is a per thread process. The stack is very fast and is used for value types. - Heap allows objects to be allocated or deallocated in a random order. - Variables allocated on the heap have their memory allocated at run time and accessing this memory is a bit slower, but the heap size is only limited by the size of virtual memory. - The heap requires the overhead of a garbage collector to keep things in order. - reference type variables are stored in the heap. And is a per-application process
  • 9.
  • 10.
    Garbage Collection - processof cleaning up the heap. - managed languages such as C# as well as dynamic languages such as Ruby - in Objective-C, you allocate memory as you need and specify pointers vs value types explicitly. When you’re done with the variable, you deallocate it yourself. - Determining what objects and memory are subject to collection requires overhead and can slow things down – It’s undecidable will a process ever be complete, therefore it’s not possible to know if memory will ever not be needed - reducing the memory size of the heap - Tracing is the most widely used method of garbage collection. - As program runs, the garbage collector will take a look at a set of “root” objects and their references, and trace those references through the stack. - As the trace runs, the GC will identify objects that are not traceable which are then deallocated and the memory freed.
  • 11.
    Garbage Collection - Ifobjects aren’t referenced they are targeted for deallocation - Disadvantages : When will the GC get around to executing? – - implementing various flavors of generational (or ephemeral) implementations.
  • 12.
    Value types andreference types A variable can store a value of a certain type. The data types can be divided into value type and reference type. The differentiation between value type and reference type depends on two features. Those are where the variables are stored in memory and how they behave with an assignment statement. The key difference between the value type and reference type is that a value type holds a data value within its own memory space while a reference type holds a pointer to another memory location that holds the data. Value types => bool, byte, char, decimal, double, float, int, long, uint, ulong, ushort, enum, struct A reference type contains a pointer to another memory location that holds the real data. Reference types => class, interface, delegate, string, object, dynamic, arrays If you assign a value type variable to another variable, the value is copied directly.
  • 13.
    Value types andreference types The value types can be divided into two categories. They are predefined types and user-defined types. The predefined types are provided by the programming language. The user can also create value types. Two such user-defined value types are structure and enumerations.
  • 14.
    Value types andreference types
  • 15.
    Finalizer & Dispose -when we create objects that include unmanaged resources such as windows, files, network and database connections, we must explicitly release those resources after using them in our applications. This can be done by using finalizers, implementing Dispose method from the IDisposable interface. What is a finalizer? Finalizers (which are also called destructors) are used to perform any necessary final clean-up when a class instance is being collected by the garbage collector. Some important points about finalizers are: A class can have only one finalizer, A finalizer does not have modifiers or parameters, Finalizers cannot be called explicitly, they are called by the garbage collector (GC) when the GC considers the object eligible for finalization. They are also called when the program finishes in .NET framework applications. Dispose Method If our application uses an expensive external resource, we should then release the resource explicitly. We can do this by implementing Dispose method from IDisposable interface. By this way, we can improve the performance of our application as well.
  • 16.
    THE COMPILATION PROCESS i. LexicalAnalysis ii. Parsing iii. Semantic Analysis iv. Optimization v. Code Generation
  • 17.
    Lexical Analysis Lexical Analysissimply analyzes the code that’s passed to the compiler and splits it into tokens. The program within the compiler that does this is called the lexer. So, using our code sample, the lexer will generate these pseudocode tokens (using tuples): The thing being analyzed by the lexer is the lexeme. A token is what’s produced from this analysis.
  • 18.
    Parsing After the lexerhas tokenized the incoming code string, the parser takes over, applying the tokens to the rules of the language – also known as a formalized grammar. parse their meaning and, essentially, what they’re supposed to mean. A parser analyzes the tokens and figures out the implicit structure:
  • 19.
    Semantic Analysis Lexical Scoping Semantic Analysis iswhere the compiler tries to figure out what you’re trying to do.
  • 20.
    Optimization the longest. little tweaksto make your code smaller, faster, and use less memory and power (which is important if you’re writing code for phones)
  • 21.
    Code Generation - packageit up - will compile code text files into an intermediate structure, which will be further compiled later on. - compiles into an actual second language called IL (or MSIL). - Just In Time
  • 22.
    CREDITS: This presentationtemplate was created by Slidesgo, including icons by Flaticon,and infographics & images by Freepik Thanks! sophieobomighie@outlook.com
  • 23.
    ● https://bigmachine.io/products/the-imposters-handbook/ ● https://www.liquisearch.com/memory_model_programming/history_and_significance ●https://medium.com/c-programming/c-memory-management-part-1-c03741c24e4b ● https://www.differencebetween.com/difference-between-value-type-and-vs-reference- type/#:~:text=What%20is%20the%20Difference%20Between%20Value%20Type%20and,%20Stored%20Location%20 %203%20more%20rows%20 ● http://computer-programming-forum.com/4-csharp/eca1cac70ad2f910.htm ● https://docs.microsoft.com/en-us/dotnet/standard/clr ● https://www.youtube.com/watch?v=clOUdVDDzIM ● http://joeduffyblog.com/2007/11/10/clr-20-memory-model/ ● https://medium.com/c-programming/c-memory-management-part-2-finalizer-dispose-d3b3e43c08d1 ● https://medium.com/c-programming/c-memory-management-part-3-garbage-collection-18faf118cbf1 ● https://www.youtube.com/watch?v=-JOkkn1ET8c ● https://www.youtube.com/watch?v=9FEfy9y0fFQ ● https://www.youtube.com/watch?v=clOUdVDDzIM Resources