是否缓存 - GetCustomAttributes

18

我目前有一个函数:

public static Attribute GetAttribute(MemberInfo Member, Type AttributeType)
{
    Object[] Attributes = Member.GetCustomAttributes(AttributeType, true);

    if (Attributes.Length > 0)
        return (Attribute)Attributes[0];
    else
        return null;
}

我在想是否值得将属性上的所有属性缓存到Attribute = _cache[MemberInfo][Type] 字典中,

这需要使用GetCustomAttributes而不带任何类型参数,然后枚举结果。这值得吗?

6个回答

23

如果您将方法的主体替换为以下内容,则可以更好地节约成本:

return Attribute.GetCustomAttribute(Member, AttributeType,false); // only look in the current member and don't go up the inheritance tree.

如果您确实需要按类型进行缓存:
public static class MyCacheFor<T>
{
    static MyCacheFor()
    {
        // grab the data
        Value = ExtractExpensiveData(typeof(T));
    }

    public static readonly MyExpensiveToExtractData Value;

    private static MyExpensiveToExtractData ExtractExpensiveData(Type type)
    {
        // ...
    }
}

Beats字典查找每次。此外,它是线程安全的:)欢呼, 弗洛里安 附言:取决于您调用此功能的频率。我有一些情况下,使用反射进行大量序列化确实需要缓存,通常,您要测量性能增益与内存使用增加之间的比较。检测您的内存使用并分析CPU时间。

我正在通过反射进行序列化,这表明在某些时候值得这样做。然而正如大家所说 - 在没有问题之前优化是没有意义的 :) 干杯 - user164771
5
在这种情况下,让我分享一个技巧: 如果你要缓存一个键是类型的东西,请使用泛型类型而不是哈希表。我已经更新了上面的代码。 - Florian Doyon
@FlorianDoyon 不错,但如果你只有运行时的 System.Type 实例,它将无法工作。 - marsze
当然可以,假设您有IStaticCache,并且StaticCache<TKey>具有从TKey类型派生值的静态构造函数(例如:更快的枚举ToString()实现),那么您可以执行以下操作:IStaticCache cache = typeof(StaticTypeCache<>).MakeGeneric(foo) as IStaticCache - Florian Doyon
ConcurrentDictionary 也是线程安全的。 - Mike Flynn

6
唯一确定的方法就是对其进行分析。如果这听起来像陈词滥调,我很抱歉。但是陈词滥调之所以成为陈词滥调,通常是因为它是真实的。
缓存属性实际上会使代码更加复杂,也更容易出错。因此,在您决定之前,您可能需要考虑开发时间。
所以像优化一样,除非必须,否则不要这样做。
根据我的经验(我谈论的是类似AutoCAD的Windows应用程序,具有大量的点击编辑GUI操作和大量的数字计算),自定义属性的读取从未成为性能瓶颈,甚至没有一次。

唉,我没有可用的分析工具来进行适当的测试。这可能还为时过早,因为它是我应用程序中相对较低级别的函数,我想要充分利用它。 - user164771
Courtney: 你可以通过在重复的循环中调用每个实现并测量每个循环运行所需的时间来进行简单的性能分析。在这种情况下,你不需要真正的分析器。 - Antoine Aubry

5
我刚刚遇到了一个情况,其中GetCustomAttributes成为了性能瓶颈。在我的情况下,它被调用了数十万次,并且数据集中包含许多行,这使得问题容易被隔离。缓存属性解决了这个问题。
初步测试表明,在现代计算机上进行约5000次调用时,性能影响几乎不可察觉。(随着数据集大小的增加,它变得极为明显)。
我一般同意其他回答关于过早优化的看法,然而,在CPU指令和DB调用的范围内,我建议GetCustomAttributes更倾向于后者。

你是如何进行缓存的? - Mike Flynn
@MikeFlynn 这很可能是使用情况相关的。但是这个问题的被接受的答案提供了一个起点。 - TTT

4

你的问题是过早优化的一个案例。

你不了解反射类的内部工作原理,因此对于多次调用GetCustomAttributes方法的性能影响做出了假设。该方法本身可能已经缓存了其输出,这意味着你的代码实际上会增加额外开销而没有性能提升。

节省你的大脑运算能力去思考那些你已经知道存在问题的事情吧!


我本来在问题中想说的是,但最终将其编辑删除了,我不知道它是否在内部执行该操作。 - user164771
它应该被命名为“如何优化GetCustomAttributes”,因为这是一个瓶颈。在我的情况下,我使用了缓存,使得我的程序启动速度快了5-6秒。 - Konrad

3

2

你是否真的遇到了性能问题?如果没有,那么在需要之前不要这样做。

这可能有助于取决于你使用相同参数调用该方法的频率。如果每个MemberInfoType组合只调用一次,则不会有任何好处。即使你缓存它,你也是在以速度换取内存消耗。这对你的应用程序可能没问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接