mercredi 3 juin 2015

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()?





Aucun commentaire:

Enregistrer un commentaire