检测不可变量的高效方法?

时间:2013-11-28 15:03:36

标签: c# multithreading immutability deep-copy

我有一个实用程序,旨在传递我们系统周围的对象。由于它是一个多线程环境,因此该实用程序会对其传递的每个对象进行深层复制,以防止出现任何线程安全问题。我正在努力转换我们的系统以使用不可变对象来消除对此副本的需求。我想知道检测对象是不可变的最好(最快)方法是什么?

我的第一个想法就是了解我们在所有不可变对象(MessageAttribute)上放置的属性。正如您从下面的性能配置文件中看到的那样,它会受到很大影响(大约是所有其他检查执行时间的10倍)。

enter image description here

我怎样才能检测到我的不可变通过?我可以做一个typeof()比较,看起来效果更好,但这看起来相当笨拙,而且随着我们一直添加更多不可变的东西,它将是难以维护的。

编辑:我忘了提到布尔值被重构为变量以进行分析,实际上,结果存储在isDefined中的表达式实际上是在else if语句,因此在此配置文件中显示的内容将减少约10倍(我更关心平均执行时间而不是绝对执行时间)。

4 个答案:

答案 0 :(得分:4)

创建一个接口(例如IImmutable)并在所有不可变类上使用它。

您只需要使用typeof()检查此接口以检测不可变的。

typeof()是一个编译时检查,因此没有性能损失。

答案 1 :(得分:3)

您仅在isDefined分支中使用else,该分支比then分支少10倍。仅在需要时计算值。这应该将其成本降低10倍。

除此之外,您可以为计算引入缓存。您可能检查的类型很少,因此缓存很小。

答案 2 :(得分:2)

我只是缓存结果,因为类型的属性不会改变。

public class SomeHelperClass
{
    private static readonly ConcurrentDictionary<Type, bool> messageAttributesCache = new ConcurrentDictionary<Type, bool>();
    private static readonly Type messageAttributeType = typeof(MessageAttribute);

    public static bool IsMessageAttributeDefined(Type type)
    {
        bool isDefined = false;
        if (messageAttributesCache.TryGetValue(type, out isDefined))
        {
            return isDefined;
        }
        isDefined = type.IsDefined(messageAttributeType, false);
        return messageAttributesCache[type] = isDefined;
    }
}

然后使用

bool isDefined = SomeHelperClass.IsMessageAttributeDefined(type);

你可以使解决方案通用,我只是想一想这是一些快速丑陋的代码。但这会更好。

答案 3 :(得分:1)

我最终实现了一个在静态构造函数中初始化的Hash集,并获得了我想要传递的所有类型。

private static HashSet<Type> m_PassableTypes; // 


static SynthesisExtensions() { // 
    m_PassableTypes = new HashSet<Type>();
    foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) {
        foreach (Type type in assembly.GetTypes()) {
            if (type.IsValueType || type == typeof (string) || type.Module.Name == "FSharp.Core.dll" ||
                type.IsDefined(typeof (MessageAttribute), false)) {
                m_PassableTypes.Add(type);
            }
        }
    }
}

这使我可以执行一个非常快速的HashSet查找,这样可以提高性能。

    Type type = instance.GetType();

    if (m_PassableTypes.Contains(type)) {
        // cache the self-reference
        referenceCache.Add(instance, instance);
        // return the value itself
        return instance;
    }

感谢您的帮助!我欢迎任何有关此解决方案的想法