Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Advantage of using CustomAttributes vs GetCustomAttributes()

I noticed today that some new properties had appeared in my intellisense on the System.Type object for my .NET 4.5 projects. Among these was one called CustomAttributes.

I was intrigued by this since I previously had understood that GetCustomAttributes was one of the most expensive reflection calls (DynamicInvoke and the like aside, of course). As I understand it, every call to GetCustomAttributes results in calling the constructors for the attributes (and thus a memory allocation). I've often resorted to caching the custom attributes separately to avoid performance bottlenecks when processing large numbers of types and such.

So, I wrote up a test to see if CustomAttributes was any more performant than GetCustomAttributes:

static void Main(string[] args)
{
    var sw = Stopwatch.StartNew();

    Debug.WriteLine(typeof(Attributed).GetType());

    for (int i = 0; i < 10000; i++)
    {
        var attrs = typeof(Attributed)
            .CustomAttributes
            .Select(a => a.AttributeType)
            .ToList();
    }

    sw.Stop();
    Debug.WriteLine("Using .NET 4.5 CustomAttributes property: {0}", sw.Elapsed);

    sw = Stopwatch.StartNew();

    for (int i = 0; i < 10000; i++)
    {
        var attrs = typeof(Attributed)
            .GetCustomAttributes(true)
            .Select(a => a.GetType())
            .ToList();
    }

    sw.Stop();
    Debug.WriteLine("Using GetCustomAttributes method: {0}", sw.Elapsed);
}

With some test classes:

[Dummy]
[Dummy]
[Dummy]
[Dummy]
[Dummy]
[Dummy]
class Attributed
{
}

[AttributeUsage(AttributeTargets.Class, AllowMultiple=true)]
class DummyAttribute : Attribute
{
    public DummyAttribute()
    {
    }
}

The results were surprising:

System.RuntimeType
Using .NET 4.5 CustomAttributes property: 00:00:00.1351259
Using GetCustomAttributes method: 00:00:00.0803161

The new CustomAttributes property was actually slower than the existing GetCustomAttributes method!

Debugging further, I discovered that the attribute constructors were not called for iterating CustomAttributes (which I expected since it looks like it is just reading the metadata). Yet somehow, it was slower than GetCustomAttributes which calls constructors.

My Question

Personally I think it is more readable to use the new property, but the cost is 1.5x-ish slower performance.

So, what advantage is there, if any, of using CustomAttributes instead of GetCustomAttributes()?

I'm assuming the situation where we are simply checking to see if an attribute of some type exists on the clas...not using methods or properties on the instance of the attribute.

like image 340
Los Frijoles Avatar asked Jun 04 '15 00:06

Los Frijoles


People also ask

Why use Custom attributes in c#?

Attributes are metadata extensions that give additional information to the compiler about the elements in the program code at runtime. Attributes are used to impose conditions or to increase the efficiency of a piece of code.

Why do we need to use attributes?

Attributes provide a way of associating information with code in a declarative way. They can also provide a reusable element that can be applied to a variety of targets. Consider the [Obsolete] attribute. It can be applied to classes, structs, methods, constructors, and more.

How to Get value of Custom Attribute c#?

Retrieving a custom attribute is a simple process. First, declare an instance of the attribute you want to retrieve. Then, use the Attribute. GetCustomAttribute method to initialize the new attribute to the value of the attribute you want to retrieve.

How to determine Attribute in c#?

By using reflection, you can retrieve the information that was defined with custom attributes. The key method is GetCustomAttributes , which returns an array of objects that are the run-time equivalents of the source code attributes.


2 Answers

You are making a traditional benchmarking mistake, one that makes many .NET programmers think that Reflection is slow. Slower than it actually is. Reflection is very lazy, you don't pay for it when you don't use it. Which makes your first measurement include all the cost of page-faulting the metadata into RAM and setup the type info reflection cache. That cost is not included in the second measurement, making GetCustomAttributes() look better than it actually is.

Always include a loop around the benchmark code, run it 10 times. You'll now see that the CustomAttributes property isn't actually that slow, I measure it at (roughly) 0.083 vs 0.063 seconds, ~30% slower.

The CustomAttributes property needed to be added in .NET 4.5 to support the language projection for WinRT. You cannot use GetCustomAttributes() in a Store, Phone or PCL project. Reflection is very different in WinRT, an inevitable side-effect of it being a COM based api. Implementation code is enough to make anyone's eyes bleed but the broad outline is that the property is implemented in C# and the method is implemented in the CLR. The C# code needs to do more work to handle the language projection details so is inevitably slower.

So just keep using GetCustomAttributes(), use the property when you have to. A 30% speed difference isn't otherwise a drastic reason to compromise style and readability, apply your common sense.

like image 102
Hans Passant Avatar answered Oct 20 '22 14:10

Hans Passant


An important difference seems to be that CustomAttributes returns IEnumerable<CustomAttributeData> while GetCustomAttributes returns object[] containing instances derived from Attribute.

like image 1
sjb-sjb Avatar answered Oct 20 '22 15:10

sjb-sjb