How slow is .NET Reflection?

I’ve run into a situation where I’d like to use a small bit of Reflection. While this particular use that I have in mind is pretty simple, the method to which I will be adding the Reflection can potentially be called tens of thousands of times per day (if not more), so it has to be fast. Reflection has a reputation as anything but, so I’d like to see just how slow is Reflection?

Measuring Slowness

I’m going to measure efficiency (or slowness) using the actual code I intend to use in my application sandwiched between time snapshot functionality provided by .NET’s StopWatch object. For capturing timing data, DateTime is another possibility, but, as I quickly discovered, DateTime is not efficient enough to capture the time snapshot data I needed.

I’ll take measurements for different scenarios: single call, looped a hundred times, a thousand, etc. to gather total time elapsed for each.

The time recording code will look like:

   1: Stopwatch Elapsed = new Stopwatch();
   2:  
   3: for (var i = 0; i < nIterations; i++)
   4: {
   5:     Elapsed.Start();
   6:     // do something
   7:     Elapsed.Stop();
   8: }
View Plain

Pretty straightforward. Record start time. Do something. Get stop time. You get Ticks and Milliseconds from StopWatch’s ElapsedTicks and ElapsedMilliseconds properties.

All test results will come from Release builds of the sample application. Test results will be dumped to a text file. Full sample code and VS2008 project are attached below.

The Reflection Code

As mentioned above, the Reflection code I want to use is very simple:

   1: string strThisMethodName = MethodBase.GetCurrentMethod ().Name;
View Plain

It just gets the name of the currently executing method. Real-world use then uses that method name as part of a string that gets recorded to a logging system.

For purposes of testing, I’m going to leave out the assembly of the string and the subsequent logging. Building the string is going to happen with or without the Reflection piece. So is the logging. I’ll therefore exclude them from the testing.

Testing

Here is the full method that will do the testing, including the single line of Reflection code whose performance I want to measure:

   1: static private void RunWithIterations (int nIterations)
   2: {
   3:     Debug.WriteLine ("");
   4:     Debug.WriteLine ("Running with " + nIterations + " iterations...");
   5:  
   6:     sw.WriteLine ("");
   7:     sw.WriteLine ("Running with " + nIterations + " iterations...");
   8:  
   9:     Stopwatch Elapsed = new Stopwatch();
  10:  
  11:     for (var i = 0; i < nIterations; i++)
  12:     {
  13:         Elapsed.Start();
  14:         string strThisMethodName = MethodBase.GetCurrentMethod ().Name;
  15:         Elapsed.Stop();
  16:     }
  17:  
  18:     Debug.WriteLine ("Total elapsed time (ticks) [" + Elapsed.ElapsedTicks + "]");
  19:     Debug.WriteLine ("Total elapsed time (ms) [" + Elapsed.ElapsedMilliseconds + "]");
  20:  
  21:     sw.WriteLine ("Total elapsed time (ticks) [" + Elapsed.ElapsedTicks + "]");
  22:     sw.WriteLine ("Total elapsed time (ms) [" + Elapsed.ElapsedMilliseconds + "]");
  23: }
View Plain

You can vary the iterations by use of the nIterations parameter. This allows for single or multiple test scenarios.

Results

If I run the above code with nIterations = 1, I get:

   1: Running with 1 iterations...
   2: Total elapsed time (ticks) [2393]
   3: Total elapsed time (ms) [0]
View Plain

Not bad. Let’s try 100:

   1: Running with 100 iterations...
   2: Total elapsed time (ticks) [4980]
   3: Total elapsed time (ms) [0]
View Plain

Now, let’s go ahead and run the full spread: 1 iteration all the way to 1 million. Here are the results:

Running with 1 iterations…
Total elapsed time (ticks) [2393]
Total elapsed time (ms) [0]

Running with 100 iterations…
Total elapsed time (ticks) [4980]
Total elapsed time (ms) [0]

Running with 1000 iterations…
Total elapsed time (ticks) [48869]
Total elapsed time (ms) [3]

Running with 10000 iterations…
Total elapsed time (ticks) [529298]
Total elapsed time (ms) [36]

Running with 100000 iterations…
Total elapsed time (ticks) [5297636]
Total elapsed time (ms) [369]

Running with 1000000 iterations…
Total elapsed time (ticks) [51573509]
Total elapsed time (ms) [3601]

My overall opinion is ‘not too bad’. Even at 1,000,000 calls, efficiency is not impacted. Also, given that the Reflection operation is just a small part of the overall operation the real-world application performs, the time increase is insignificant.

Reflection Caching

Turns out Reflection has a caching mechanism:

[…] reflection and the runtime have a number of caches in place to reduce the number of times the reflection runtime has to travel to metadata to pick up the bits.

Even better. There may be a small performance hit the first time Reflection has to hit the metadata, but after that you’re all cache and response time should be very fast.