【问题标题】:Advantage of using CustomAttributes vs GetCustomAttributes()使用 CustomAttributes 与 GetCustomAttributes() 的优势
【发布时间】:2015-08-18 09:58:02
【问题描述】:

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

我对此很感兴趣,因为我之前知道GetCustomAttributes 是最昂贵的反射调用之一(当然,DynamicInvoke 和类似调用除外)。据我了解,每次调用GetCustomAttributes 都会调用属性的构造函数(从而调用内存分配)。我经常求助于单独缓存自定义属性,以避免在处理大量类型等时出现性能瓶颈。

所以,我写了一个测试,看看CustomAttributes 是否比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 方法慢!

进一步调试,我发现没有调用属性构造函数来迭代CustomAttributes(这是我预料到的,因为它看起来只是在读取元数据)。然而不知何故,它比调用构造函数的GetCustomAttributes 慢。

我的问题

我个人认为使用新属性更具可读性,但代价是性能降低 1.5 倍。

那么,如果有的话,使用CustomAttributes 代替GetCustomAttributes() 有什么好处?

我假设我们只是检查类中是否存在某种类型的属性...而不是使用属性实例上的方法或属性。

【问题讨论】:

  • 考虑到基准的简单性,这只是一个微小的差异。这可能只是在误差范围内被丢弃。你比较过这些 API 的实际实现吗?
  • 是的,这是一个非常小的差异,但是当增加迭代次数时它确实可以扩展并保持 1.5 倍的比率,这意味着当使用自定义迭代大量事物时它可能会产生影响属性。我正在尝试找到一个程序集来指向 ILSpy 以查看实现(除非我可以在他们首先在线的参考源中找到它)
  • 老实说,我更感兴趣的是它为什么变慢。我本来预计它会明显更快,因为它只是读出 GetCustomAttributes 无论如何都需要做的类型的元数据。也许获得ConstructorInfo 和其他东西的过程比我想象的要贵?

标签: c# .net reflection custom-attributes


【解决方案1】:

您犯了一个传统的基准测试错误,这使许多 .NET 程序员认为反射很慢。比实际慢。反射很懒,不用的时候不用花钱。这使得您的 first 测量包括将元数据页面错误放入 RAM 和设置类型信息反射缓存的所有成本。该成本未包含在第二次测量中,这使得 GetCustomAttributes() 看起来比实际更好。

始终在基准代码周围包含一个循环,运行 10 次。您现在会看到 CustomAttributes 属性实际上并没有那么慢,我测量它时(大约)0.083 秒对 0.063 秒,慢了约 30%。

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

所以请继续使用 GetCustomAttributes(),在必要时使用该属性。 30% 的速度差异并不是影响风格和可读性的严重理由,请运用您的常识。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-03
    相关资源
    最近更新 更多