Recipe 3.32. Determining Where Boxing and Unboxing Occur
You have a project consisting of some very complex code that is a performance bottleneck for the entire application. You have been assigned to increase performance, but you do not know where to start looking.
A great way to start looking for performance problems is to use a profiling tool to see whether boxing is actually causing you any kind of problem in the first place. A profiler will show you exactly what allocations are occurring and in what volume. There are several profilers on the market; some are free and others are not.
If you have already established through profiling that boxing is definitely causing a problem but you are still having trouble working out where it's occurring, then you can use the Ildasm disassembler tool that is packaged with VS.NET. With Ildasm you can convert an entire project to its equivalent IL code and then dump the IL to a text file. To do this, Ildasm has several command-line switches, one of which is the /output switch. This switch is used as follows:
ildasm Proj1.dll /output:Proj1.il
This command will disassemble the file Proj1.dll and then write the disassembled IL to the file Proj1.il.
A second useful command-line switch is /source. This switch shows the original code (C#, VB.NET, etc.) in which this DLL was written, as well as the IL that was compiled from each of these source lines. Note that the DLL must be built with debugging enabled. This switch is used as follows:
ildasm Proj1.dll /output:Proj1.il /source
We prefer the second method of invoking Ildasm, since the original source is included, preventing you from getting lost in all of the IL code.
After running Ildasm from the command line, open the resulting IL code file into VS.NET or your favorite editor. Inside the editor, do a text search for the words box and unbox. This will find all occurrences of boxing and unboxing operations.
Using this information, you have pinpointed the problem areas. Now, you can turn your attention to them to see if there is any way to prevent or minimize the boxing/unboxing operations.
When a boxing or unboxing operation occurs in code, whether it was implicit or explicit, the IL generated includes the box or unbox command. For example, the following C# code:
int valType = 1; object boxedValType = valType; valType = (int)boxedValType;
compiles to the following IL code:
//000883: int valType = 1; IL_0000: ldc.i4.1 IL_0001: stloc.0 //000884: object boxedValType = valType; IL_0002: ldloc.0 IL_0003: box [mscorlib]System.Int32 IL_0008: stloc.1 //000898: int valType = (int) boxedValType; IL_0061: ldloc.1 IL_0062: unbox [mscorlib]System.Int32 IL_0067: ldind.i4
Notice the box and unbox commands in the previous IL code. IL makes it very apparent when a boxing or unboxing operation occurs. You can use this to your advantage to find and hopefully prevent a boxing operation from occurring.
The following can help prevent or eliminate boxing:
See the "Boxing Conversion" and "Unboxing Conversion" topics in the MSDN documentation.
Here is a list of some available profiling tools: