Contact   •   Products   •   Search

Rick Strahl's Web Log

Wind, waves, code and everything in between...
ASP.NET • C# • HTML5 • JavaScript • AngularJs

.Net Reflection and Performance


I ran into an interesting post today on the ASP. Net NewsGroup regarding Reflection. Somebody mentioned using Reflection inside of an ASP.Net page and was wondering whether this would be a big performance drain on his application. One response later the original poster walks away thinking that a single call to Reflection is going to completely kill the performance of his Web application.

 

This isn’t the first time I've heard concerns over this – there seems to be a lot of misconception of how Reflection works and what sort of impact it has on an application. Reflection allows querying information out of an assembly dynamically and setting and retrieving values from properties/fields as well as dynamically invoking methods at runtime providing a sort of ‘Evaluate’ functionality assuming you have a reference to an object you want to call.

 

This process is slow compared to direct access of a property, field or method, but it’s hardly a show stopper if used sparingly. You can also bet that the .Net Framework and especially ASP.Net use Reflection internally a fair amount to provide dynamic execution of code and controls, so making one or two calls to Reflection are hardly going to impact performance.

 

I ran a few very simple tests just to verify that I'M not completely off my rocker here, and sure enough adding a couple of reflection calls to even an empty ASPX page resulted in nearly identical performance results in ACT. The general variance of ACT in short tests actually had the reflection test ahead in 1 of the tests - all the others were also very close with close 250 requests a second against the sample page. In short for a typical ASP.Net page call the overhead was minmal.

 

Next I ran a couple of simple timing tests in a WinForms app:

 

//#define CallMethod

//#define GetField

#define SetField

 

 

protected string Output = "";

 

 

private void btnStraight_Click(object sender, System.EventArgs e)

{

      this.Output = DateTime.Now.ToString();

 

      DateTime Start = DateTime.Now;

      for (int x = 0; x < 100000; x++)

      {

#if GetField

            // *** Get Property Test - note we have to set the value here or else the

            // *** compiler will optimize the assignment

            this.Output = DateTime.Now.ToString();

            string Value = this.Output;

#endif

#if SetField

            // *** Set Property Test

            this.Output = DateTime.Now.ToString();

#endif

#if CallMethod

            this.Output = this.ReturnDate();

#endif

     

      }

      DateTime Stop = DateTime.Now;

 

      this.lblResult.Text = ((TimeSpan) Stop.Subtract(Start)).Ticks.ToString("N") + "Ticks.";

}

 

private void btnReflection_Click(object sender, System.EventArgs e)

{

      this.Output = DateTime.Now.ToString();

 

      DateTime Start = DateTime.Now;

      for (int x = 0; x < 100000; x++)

      {

#if GetField

            this.Output = DateTime.Now.ToString();

            string Value = (string) this.GetType().GetField( "Output",BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this); //,BindingFlags.Instance | BindingFlags.NonPublic,null,null);

#endif

#if SetField

 

            // *** Set Property Test

            this.GetType().GetField( "Output",BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this,DateTime.Now.ToString()); //,BindingFlags.Instance | BindingFlags.NonPublic,null,null);

#endif

#if CallMethod

            string value = (string) this.GetType().GetMethod("ReturnDate",BindingFlags.NonPublic | BindingFlags.Instance).Invoke(this,null);

#endif

            }

      DateTime Stop = DateTime.Now;

 

      this.lblResult2.Text = ((TimeSpan) Stop.Subtract(Start)).Ticks.ToString("N") + "Ticks.";

}

 

protected string ReturnDate()

{

      return DateTime.Now.ToString();

}

 

The results here were not surprising: Reflection was roughly 2.5-3.0 times slower than direct assignment and retrieval of the property value. Method Invokation was 3.5 to 4 times slower than direct calling of a method.

 

But keep in mind that this loop ran 100,000 iterations and the entire test ran in under 900 ms without and under 2.5 to a little over 3 seconds with Reflection. The individual call times of these reflected type methods are minmal in the context of a typical application. Slower yes for sure - but having an impact on a typical application? Not likely...

 

To test this in a real world environment I checked out an ASP.Net page that uses custom databinding that I have implemented that relies fairly extensively on Reflection to bind (and unbind) data to an underlying datasource. I loaded a Web Form that has 35 databound fields on it. I ran the page with databinding enabled and then turned the databinding on the page off completely. Performance ran about 10 slower than without any databinding whatsoever – around 95 requests per second vs. around 85. I was too lazy to add ASP. Net’s default binding to all of the form’s fields but adding it to a few of them showed that the response time of the non-custom binding started falling off. I suspect if all fields were bound there’d be very little difference between my custom binding and ASP. Net’s default binding mechanism (which behind the scenes probably also uses Reflection to assign the values the DataBinder retrieves).

 

Reflection often gets a bad rap for being slow. True it's much slower than direct access, but it's important to look at performance in the proper perspective. For many operations Reflection and 'evaluative' access to properties, fields and methods provides flexibility that wouldn't otherwise be there.

 

In short, it’s a good idea to stay away from Reflection when possible, but don’t be afraid to resort to it when it provides a better or more flexible solution to your problem. The performance hit for anything but tight loop operations is likely to be minimal in the overall scheme of an application or Web Form request.

 

Related Link about Simplified Reflection Access

Make Donation


Feedback for this Post

 
# re: .Net Reflection and Performance
by Frank Camp April 11, 2004 @ 8:30am
Reminds me of Macro substitution of Visual Foxpro, both in functionality and in its reputation. It seems that you should approach them the same.
Use them if there is no better alternative.
# re: .Net Reflection and Performance
by Rick Strahl April 11, 2004 @ 11:06am
It's more like the EVALUATE() function in VFP or VB rather than a macro. You can't execute commands and the code is not 'excplicitly' compiled each time it's access (other than the JIT firing the first time a method or property is accessed).
# re: .Net Reflection and Performance
by Mike Schinkel April 11, 2004 @ 12:39pm
Seems to me the macro is only one part of .NET Reflection; the ability to execute named methods. Sounds more in whole like "data driven programming" which was the term we used in my Clipper days. I was a huge advocate of data driven programming.

Anywho, here is my somewhat related post where I referenced this as it came in while writing:
http://blogs.xtras.net/mikes/PermaLink,guid,93d29fdd-5eba-4a29-acf3-1d93dd8ac9a4.aspx
# Reflection and COM object access
by Rick Strahl's WebLog July 05, 2004 @ 12:40pm
I ran into a weird issue with accessing a COM EXE server using my Reflection helpers I posted about a while back. Looks like using InvokeMember fixes this issue although I'm struggling to see what it's doing differently than the relative MemberInfo methods.
# re: .Net Reflection and Performance
by Larry Davis May 18, 2006 @ 7:32am
how about performance of reflection across assemblies?
# re: .Net Reflection and Performance
by Rick Strahl May 18, 2006 @ 7:39am
Doesn't really make a difference after the initial load of the assembly. The only hit is the actual loading of the assembly after that it's just another assembly loaded into the current AppDomain.
# Re: Reflection....Speed Test?
by Channel 9: Techoff October 28, 2006 @ 9:18am
# Reflection to provide EVALUATE functionality - Rick Strahl's Web Log
by Rick Strahl's Web Log November 29, 2006 @ 7:36am
After answering three more questions today on how to ‘dynamically’ access a property or control on a form I thought I’d post my Reflection helpers again. I’ve put these into most articles I’ve published, but this way they are easily searchable and pointable for future reference.
# CSLA .NET - Internal interfaces & .NET - Implicit vs. Explicit implementation
by CSLA .NET January 11, 2007 @ 9:40am
Forums for CSLA .NET and the Expert VB 2005 Business Objects and C# 2005 Business Objects books by Rockford Lhotka
# Reflection and COM object access - Rick Strahl's Web Log
by Rick Strahl's Web Log February 17, 2007 @ 2:02am
I ran into a weird issue with accessing a COM EXE server using my Reflection helpers I posted about a while back. Looks like using InvokeMember fixes this issue although I'm struggling to see what it's doing differently than the relative MemberInfo methods.
# re: .Net Reflection and Performance
by Tim June 22, 2007 @ 2:57pm
I've been having problems trying to reflect across all assemblies in an application. For starters, AppDomain.CurrentDomain.GetAssemblies() doesn't always return all the assemblies in the bin folder. It's either a timing thing, or has something to do with how the app recycles. I've started down a path of loading all the assemblies in the bin folder manually, just to reflect on them, but that has some issues of its own (extra assemblies hanging out in memory, having to use a temporary app domain, etc). Is there a consistent and relatively painless way to reflect across ALL assemblies in an app's bin folder?

Any help will be appreciated.
# re: .Net Reflection and Performance
by 池雷 May 26, 2008 @ 11:02pm
What i want to know is do it will be slower in condition as following:
My web site have more than 4000 users;
I want to use reflection to set properties;

Forgive me for my bad english, for i am a chinese not good at english.

Any help is presure appreciated
# re: .Net Reflection and Performance
by Rick Strahl May 27, 2008 @ 1:37am
If you're dealing with a loaded Web site, slow is slow anyway you look at it. If code is accessed frequently in a near the limit site it has potential to slow your site and add additional load.

But you have to look at it in relative terms. First ASP.NET already does tons of Reflection based code internally. If you use databindinding (or Eval()/Bind()) of any kind all that goes through reflection. Lots of places reflection is used.

Personally I don't think that reflection usage on page level code that is something to worry about much. It's in framework code, where code loops or is frequently called where special attention really needs to be given to Reflection usage.

In the end only code profiling will help you isolate where bottlenecks in your apps are and my guess it won't be on a few cases of Reflection usage.
# re: .Net Reflection and Performance
by 池雷 May 27, 2008 @ 6:29pm
Thanks for your explanation, I think I know sth. about reflection now. Your help is valuable.

I notice that your answer was posted at 1:37 am, is it time zone difference or working hard?

best regard.
# re: .Net Reflection and Performance
by Vikas Burman June 18, 2008 @ 10:21am
Hi Rick,

Your's advice has always been the most important one since my VFP days.

I am wondering about the impact of reflection's slow nature in a specific context - I have a web service which takes on a message (a serialized object), reads it, refer to an xml to find out mapped information and use reflection to load required assembly, create require class's object and execute required method to get the result back which is returned to caller wrapped in a message again.

Now in my scenario there is a possibility that this web service will be dealing with about 10,000 messages at peak time. Having load balancer in place for the server where web service is deployed, would reflection used in this context be a performance bottelneck?

Thanks,
Vikas
# re: .Net Reflection and Performance
by Brian Griffin December 23, 2008 @ 1:13pm
Rick,

Good article. You raise a very valuable point in that absolutism should be doubted and verified. Microsoft does use extensive reflection within the Page processing life cycle. Any databound control uses reflection. A great example is the datagrid. Even more interesting is how Microsoft managed reflection overhead in the DataGrid.

I have personally observed code where developers will implement custom data binding to emit rows from a Dataset or DataReader and in their algorithm will re-reflect the Properties Collection to get to the PropertyDescriptors the Properties. Apparently the errant developers did not realize that the PropertyDescriptors were reusable and that the really expensive reflection lies in the generation of the Properties collection. Making it worse is that version 1.1 of the framework does not cache the PropertyDescriptorsCollection. Microsoft's design of the DataGrid WebControl showed a keen awareness of this and they really optimized the grid to prevent re-reflection by caching their property descriptors and reusing them.

My point is this: not only do people have to be concerned with performance regarding the use of PropertyDescriptors and invocation of Methods via Reflection, they need to be keenly aware of how they are USING reflection.

As developers we frequently talk about code re-use, frameworks, and maintainable code but without Reflection how could you for example write a data binding algorithm to deal with disparate datasources (e.g. DataReader, DataSet, collection of Objects)? Many developers would have Dataset specific code, DataReader specific code and so on. Using reflection coupled with a knowledge of the System.ComponentModel namespace a develoepr could create single, scalable, performant software layer that binds any of the objects that I mentioned). Reflection is powerful and if misused can create performance issues. As you rightly point out; when used properly developers should not have significant impact on their systems performance.

In my opinion Reflection is the gateway to the next "level" in .Net programming.
# re: .Net Reflection and Performance
by Matic January 22, 2009 @ 12:57pm
Hi Rick!

I'm also wondering should I use a reflaction in my App or not. Browsing the web for the answer wasn't very successful, yet...;)

So, as I assumed and you also pointed out, .NET internally uses reflection as well. But there is a fact, that reflection is slower, which is obviuos, since the code is not compiled, meaning that the function doesn't know what kind of object will it get, for example.

My case, where using reflection would come very handy is this. I'm building a multilayer app and I would like to have a generic DataAccessLayer class, to handle most of object and their communication with DB. The idea is to have a function that handles an update and /or insert events for any kind of object passed to it. It gets a BaseClass object from which all the others are dervied from. Than I would like to use reflection, to get the type of it and get it's properties, methods and parameters. It would save me a bunch of time during development, but I'm concerened about performance. Since this would be a part of framework, it would be implemented largely and in different type of apps (from webpages to bussiness apps, intranets...). I wonder,if this is reasonable,or it is better to code every DB class for itself, just for perfomance sake?

Her is a snippet of my code, where I use reflection. It is called every time I insert or update ANY object:

//generic request for insert / update
public void Change(Basic item)
{
PropertyInfo[] properties = item.GetType().GetProperties();
NeoDatabaseAccess nda = new NeoDatabaseAccess();
SqlCommand cmd = nda.GetCommand("sp" + item.Entity + "_Change");

//get each property in the item
foreach (PropertyInfo property in properties)
{
if (property.Name != "EntityID" && property.Name != "Entity" && property.Name != "Instance")
{
//add each property as a parameter
MethodInfo method = item.GetType().GetMethod("get_" + property.Name);
ParameterInfo[] info = item.GetType().GetMethod("get_" + property.Name).GetParameters();
cmd.Parameters.AddWithValue("@" + property.Name, method.Invoke(item, info));
}
}
cmd.Parameters["@InstanceID"].Direction = ParameterDirection.InputOutput;
item.InstanceID = Convert.ToInt32(cmd.ExecuteScalar());

nda.Dispose();
}

So any poniter, suggestion or opinion would be greatly appreciated!

Thanks in advance, Matic
# .Net Reflection and Performance
by DotNetKicks.com February 03, 2009 @ 1:54pm
You've been kicked (a good thing) - Trackback from DotNetKicks.com
# re: .Net Reflection and Performance
by Kenneth Xu May 19, 2009 @ 9:33pm
Nice article! I found this post when I was surprise by my recent test result to find that the reflection call is 1500x-2000x slower for a method that takes two parameters, which is typical use case. And my test already reusing the MethodInfo object. It is the Invoke only that is this slow. Compare to your test result, it is very different! Test code can be found here:

http://kennethxu.blogspot.com/2009/05/strong-typed-high-performance_15.html
# You’re Not Your Data Access
by Rob Conery June 11, 2009 @ 8:51pm
Seems I touched off a bit of a “swirl” with a comment I made on my last blog post: I think, in general
# re: .Net Reflection and Performance
by Chris September 02, 2009 @ 7:13am
Rick, Thanks for posting information on reflection, the more we know about it the better off we all are. I have a question that I can't seem to find the answer to. Is this considered reflection? if(objectA is Animal)
{
Animal Animal1 = objectA as Animal;
}

I guess my question is this: Does 'object is Type' have the same performance hit as 'object.GetType()' ?
# re: .Net Reflection and Performance
by Rick Strahl September 02, 2009 @ 8:48am
@chris - no that's not reflection. That's just type casting and AS is actually pretty efficient at that. Polymorphism better not require Reflection :-}
# re: .Net Reflection and Performance
by Peter Goostree November 16, 2009 @ 9:14pm
I inherited a code base that is about 700,000 lines of ASP.Net and XML web services. It has been built by different programmers who have come and gone with project dollars over the last five years and so have their architectural patterns. One of the biggest problems this code suffers from is that lack of an API on the client side for the client applications to conform to. Therefore there are "util" classes for this and "helper" classes for that. The code duplication is high because methods are buried in places that do not make sense. Developers struggle trying to find the path. Classic case of spaghetti code. To gain full control of the entire application domain takes about 3-6 months. To deal with this, I am trying out an idea that uses Reflection quite a bit to transfer data from a web service response to the associated client side type that includes methods that operate on the data the DTO represents. This will be accomplished with a static method called "Map". This way there will be a distinct path for the client apps to adhere to, and it will support one of the pillars of good OO programming - Encapsulation. My colleague and I are going to be testing it's performance this week, I will respond to this thread with my findings. I hope the Reflection won't be too much of a performance impact. We'll see!
# re: .Net Reflection and Performance
by Mehdi November 18, 2009 @ 7:04pm
Rick - Good article, thanks.

StopWatch class is really helpful in performance tests: http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx
# re: .Net Reflection and Performance
by Charles Cai March 20, 2010 @ 3:00am
So I added more tests, i.e. cached reflection (we cached PropertyInfo and MethodInfo), 2 more .NET 4.0 PLINQ enabled version, one for normal, one for reflection, and the results on a dual-core PC are:

Normal test used: 1500ms
NormalPlinq test used: 786ms

Reflect test used: 2923ms

ReflectCache test used: 2576ms
ReflectCachePlinq test used: 1353ms


You can see on a dual-core PC, PLINQ doubles the performance and bring our cached reflection code FASTER than normal call; on the other hand PLINQ double the normal call performance too :)

Any other way to optimize our reflection code?
Any ways to avoid boxing/unboxing if we are dealing with value types?


Console c# source code running on VS2010 RC:

using System;
using System.Diagnostics;
using System.Reflection;
using System.Threading.Tasks;
 
namespace ConsoleApplication1
{
    class Program
    {
        private String Output { get; set; }
 
        static void Main(string[] args)
        {
            var p = new Program();
            var stopwatch = new Stopwatch();
            
            stopwatch.Start();
            p.TestNormal(stopwatch);
 
            stopwatch.Restart();
            p.TestNormalPlinq(stopwatch);
 
            stopwatch.Restart();
            p.TestReflection(stopwatch);
 
            stopwatch.Restart();
            p.TestReflectionCached(stopwatch);
 
            stopwatch.Restart();
            p.TestReflectionCachedPlinq(stopwatch);
        }
 
        string ReturnDate()
        {
            return DateTime.Now.ToString();
        }
 
        void TestNormal(Stopwatch stopwatch)
        {
            this.Output = DateTime.Now.ToString();
 
            for (int x = 0; x < 200000; x++)
            {
 
                // *** Get Property Test - note we have to set the value here or else the compiler will optimize the assignment
                this.Output = DateTime.Now.ToString();
 
                var Value = this.Output;
 
                // *** Set Property Test
                this.Output = DateTime.Now.ToString();
 
                this.Output = this.ReturnDate();
            }
 
            Debug.WriteLine("Normal test used: " + stopwatch.ElapsedMilliseconds + "ms");
        }
 
        void TestNormalPlinq(Stopwatch stopwatch)
        {
            this.Output = DateTime.Now.ToString();
 
            Parallel.For(0,
                         200000,
                         (i) =>
                             {
 
                                 // *** Get Property Test - note we have to set the value here or else the compiler will optimize the assignment
                                 this.Output = DateTime.Now.ToString();
 
                                 var Value = this.Output;
 
                                 // *** Set Property Test
                                 this.Output = DateTime.Now.ToString();
 
                                 this.Output = this.ReturnDate();
                             });
 
            Debug.WriteLine("NormalPlinq test used: " + stopwatch.ElapsedMilliseconds + "ms");
        }
 
        void TestReflection(Stopwatch stopwatch)
        {
            for (int x = 0; x < 200000; x++)
            {
                this.Output = DateTime.Now.ToString();
                string Value = (string) this.GetType().GetProperty("Output", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this, null);
                    //,BindingFlags.Instance | BindingFlags.NonPublic,null,null);
 
                // *** Set Property Test
                this.GetType().GetProperty("Output", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, DateTime.Now.ToString(), null);
                    //,BindingFlags.Instance | BindingFlags.NonPublic,null,null);
                string value = (string) this.GetType().GetMethod("ReturnDate", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(this, null);
            }
            
            Debug.WriteLine("Reflect test used: " + stopwatch.ElapsedMilliseconds + "ms");
        }
 
        void TestReflectionCached(Stopwatch stopwatch)
        {
            var pi = this.GetType().GetProperty("Output", BindingFlags.Instance | BindingFlags.NonPublic);
            var mi = this.GetType().GetMethod("ReturnDate", BindingFlags.Instance | BindingFlags.NonPublic);
 
            Func<string> getter = () => (string) pi.GetValue(this, null);
            Action<string> setter = (s) => pi.SetValue(this, s, null);
            Func<string> getMethod = () => (string) mi.Invoke(this, null);
 
            for (int x = 0; x < 200000; x++)
            {
                this.Output = DateTime.Now.ToString();
                string Value = getter();
 
                setter(DateTime.Now.ToString());
 
                string value = getMethod();
            }
 
            Debug.WriteLine("ReflectCache test used: " + stopwatch.ElapsedMilliseconds + "ms");
        }
 
        void TestReflectionCachedPlinq(Stopwatch stopwatch)
        {
            var pi = this.GetType().GetProperty("Output", BindingFlags.Instance | BindingFlags.NonPublic);
            var mi = this.GetType().GetMethod("ReturnDate", BindingFlags.Instance | BindingFlags.NonPublic);
 
            Func<string> getter = () => (string)pi.GetValue(this, null);
            Action<string> setter = (s) => pi.SetValue(this, s, null);
            Func<string> getMethod = () => (string)mi.Invoke(this, null);
 
            Parallel.For(0, 200000,
                         (i) =>
                             {
                                 this.Output = DateTime.Now.ToString();
                                 string Value = getter();
 
                                 setter(DateTime.Now.ToString());
 
                                 string value = getMethod();
                             });
 
            Debug.WriteLine("ReflectCachePlinq test used: " + stopwatch.ElapsedMilliseconds + "ms");
        }
    }
}
# re: .Net Reflection and Performance
by Kenneth Xu May 16, 2010 @ 8:40pm
> Any other way to optimize our reflection code?
Yes, bind your method to delegate and cache the delegate. You get nearly normal performance. For field access, you'll need dynamic method. See link below for detail:

http://kennethxu.blogspot.com/2009/05/strong-typed-high-performance_15.html
# re: .Net Reflection and Performance
by ivaylo_slavov September 12, 2010 @ 11:50am
Well, the PLinq tests in my opinion are not a good example for actual performance measurement, because I think the tasks get executed in parallel (let's say 2-3 at a time) , and therefore the test will complete faster than the for-loop example where each task runs after the previous one completes.
 


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2014