We have to understand which part of our (or third party, probably CLR itself) code leads to boxing of integers.
We have a rather big application where we observe high allocation rate of System.Int32
instances. With the help of Memory Profiler we see a small number of long existing Int32
instances (18, to be exact) and 20-25 thousands of Int32
allocations per second. All those objects are GC collected as Gen0 objects, system has no memory leaks and can be run for long time. When memory snapshot is created, GC is executed before snapshot, so snapshot does not contains any traces of those “temporary” objects.
All our code was specifically written to eliminate boxing whenever possible, and “by design” we are supposed to not see boxings at all. So we suspect it is some non-eliminated forgotten boxing in our code, or boxing caused by third-party component and/or CLR type itself.
System is compiled using VS2008, and uses .Net 3.5 (measurements were done in both debug and release builds, with the same behavior).
How can we (using windbg, VS2008, Memory Profiler, AQTime or any other commercially available product) detect why boxing happens ?
The process of converting a Value Type variable (char, int etc.) to a Reference Type variable (object) is called Boxing. Boxing is an implicit conversion process in which object type (super type) is used. Value Type variables are always stored in Stack memory, while Reference Type variables are stored in Heap memory.
How to prevent boxing & unboxing: Use ToString method of numeric data types such as int, double, float etc. Use for loop to enumerate on value type arrays or lists (do not use foreach loop or LINQ queries) Use for loop to enumerate on characters of string (do not use foreach loop or LINQ queries)
Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type. When the common language runtime (CLR) boxes a value type, it wraps the value inside a System. Object instance and stores it on the managed heap. Unboxing extracts the value type from the object.
When a value type is converted to object type, it is called boxing.
One of my favorite applications is CLR Profiler this will give you what you are looking for it will map your entire application showing the different generations. It's a free download from Microsoft and it's extremely powerful and simple to use. I have also included a link for how to use it. (CLR Profiler Download) (How to Use CLR Profiler)
Rather surprisingly, methods of DateTime class ToLocalTime/ToUniversalTime cause boxing.
Our application (application server) was recently modified to work "inside" in UTC only (to cope with daylight time changes etc). Our client codebase stayed 99% local time based.
Application server converts (if needed) local times to UTC times before processing, effectively causing boxing overhead on every time-related operation.
We will consider re-implementing those operations "in house", without boxing.
Have you made a static analysis of your code? Maybe NDepend can help you to find the methods and types that are boxing and unboxing values.
A trial version of NDepend is freely available, so it would be worth trying to analyze the assemblies, both yours and 3rd party.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With