使用CustomAttributes与GetCustomAttributes()的优势 [英] Advantage of using CustomAttributes vs GetCustomAttributes()

查看:734
本文介绍了使用CustomAttributes与GetCustomAttributes()的优势的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天我注意到,.NET 4.5项目的 System.Type 对象的智能感知中已经出现了一些新属性。其中一个叫做 CustomAttributes

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.

对此我很感兴趣,因为我以前了解到 GetCustomAttributes 是最昂贵的反射调用之一(当然还有 DynamicInvoke 等)。据我了解,每次对 GetCustomAttributes 的调用都会导致调用属性的构造函数(并因此调用内存)。我经常采用单独缓存自定义属性的方式,以避免在处理大量类型等时出现性能瓶颈。

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.

因此,我编写了一个测试以查看 CustomAttributes GetCustomAttributes 具有更高的性能:

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);
}

带有一些测试类:

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

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

结果令人惊讶:

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

新的实际上,CustomAttributes 属性比现有的 GetCustomAttributes 方法要慢!

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

进一步调试,我发现没有调用 CustomAttributes 来调用属性构造函数(我希望这样做,因为它看起来像是在读取元数据)。但是,以某种方式,它比调用构造函数的 GetCustomAttributes 慢。

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.

我个人认为使用新属性更易读,但成本却降低了1.5倍。

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

那么,这有什么好处是否使用了 CustomAttributes 而不是 GetCustomAttributes()

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.

推荐答案

您正在犯一个传统的基准测试错误,这个错误使许多.NET程序员认为反射很慢。比实际速度慢。反思很懒惰,不用时不用付钱。这使得您的 first 评估包括将元数据页面错误转移到RAM并设置类型信息反射缓存的所有成本。该费用未包含在第二个度量中,使GetCustomAttributes()看起来比实际情况要好。

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.

始终在基准代码周围包含一个循环,运行10次。现在,您会看到CustomAttributes属性实际上并不是 慢,我将其测量为(大约)0.083 vs 0.063秒,慢了约30%。

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.

需要在.NET 4.5中添加CustomAttributes属性,以支持WinRT的语言投影。您不能在商店,电话或PCL项目中使用GetCustomAttributes()。在WinRT中,反射非常不同,这是基于COM的api的不可避免的副作用。实现代码足以使所有人流连忘返,但是概括的概述是,该属性是用C#实现的,而该方法是使用CLR实现的。 C#代码需要做更多的工作来处理语言投影的细节,因此不可避免地会变慢。

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.

因此,只要继续使用GetCustomAttributes(),就必须使用该属性。保持30%的速度差异并不是折衷样式和可读性的激烈理由,请运用您的常识。

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.

这篇关于使用CustomAttributes与GetCustomAttributes()的优势的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆