Tuesday, April 30, 2019

GC in C#

The managed heap contains three generations; Generation 0 contains all new objects, Generation 1 contains slightly longer-lived objects, and Generation 2 contains long-lived objects

Generation 0 is dynamically sized according to the size of the processor's cache and the application's allocation rate, and typically takes less than 10 milliseconds to collect. 

Generation 1 is sized dynamically according to the allocation rate of the application and typically takes between 10 and 30 milliseconds to collect. 

Generation 2 size will depend on the allocation profile of your application, as will the time it takes to collect. It is these Generation 2 collections that will most significantly affect the performance cost of managing your applications' memory.

Large Object Heap is any object > 80 KB

Method Inlining

There is a cost associated with method calls; arguments need to be pushed on the stack or stored in registers, the method prolog and epilog need to be executed and so on. The cost of these calls can be avoided for certain methods by simply moving the method body of the method being called into the body of the caller. This is called Method In-lining. The JIT uses a number of heuristics to decide whether a method should be in-lined. The following is a list of the more significant of those (note that this is not exhaustive):
  • Methods that are greater than 32 bytes of IL will not be inlined.
  • Virtual functions are not inlined.
  • Methods that have complex flow control will not be in-lined. Complex flow control is any flow control other than if/then/else; in this case, switch or while.
  • Methods that contain exception-handling blocks are not inlined, though methods that throw exceptions are still candidates for inlining.
  • If any of the method's formal arguments are structs, the method will not be inlined.

Optimizations that Require Variable Usage Tracking

Aa number of JIT compiler optimizations require that the JIT track the usage of formal arguments and local variables; for example, when are they first used and the last time they are used in the body of the method. In version 1.0 and 1.1 of the CLR there is a limitation of 64 on the total number of variables for which the JIT will track usage. An example of an optimization which requires usage tracking is Enregistration. Enregistration is when variables are stored in processor registers as opposed to on the stack frame, for example, in RAM. Access to the Enregistered variables is significantly faster than if they are on the stack frame, even if the variable on the frame happens to be in the processor cache. Only 64 variables will be considered for Enregistration; all other variables will be pushed on the stack. There are other optimizations other than Enregistration that depend on usage tracking. The number of formal arguments and locals for a method should be kept below 64 to ensure the maximum number of JIT optimizations. Keep in mind that this number might change for future versions of the CLR.
HINT   Keep methods short. There are a number of reasons for this including method inlining, Enregistration and JIT duration.