C# 检测不可变的性能方法?
我有一个实用程序,设计用于在系统中传递对象。由于它是一个多线程环境,因此该实用程序会对它传递的每个对象进行深度复制,以防止出现任何线程安全问题。我正在将我们的系统转换为使用不可变对象,以消除对该副本的需要。我想知道检测对象不可变的最佳(最快)方法是什么 我的第一个想法是只提取我们放在所有不可变对象上的属性(MessageAttribute)。正如您从下面的性能配置文件中看到的,它需要相当多的时间(大约是我所有其他检查执行时间的10倍) 否则我如何检测通过的不可变项?我可以做一个C# 检测不可变的性能方法?,c#,multithreading,immutability,deep-copy,C#,Multithreading,Immutability,Deep Copy,我有一个实用程序,设计用于在系统中传递对象。由于它是一个多线程环境,因此该实用程序会对它传递的每个对象进行深度复制,以防止出现任何线程安全问题。我正在将我们的系统转换为使用不可变对象,以消除对该副本的需要。我想知道检测对象不可变的最佳(最快)方法是什么 我的第一个想法是只提取我们放在所有不可变对象上的属性(MessageAttribute)。正如您从下面的性能配置文件中看到的,它需要相当多的时间(大约是我所有其他检查执行时间的10倍) 否则我如何检测通过的不可变项?我可以做一个typeof()
typeof()
比较,这看起来性能更好,但这看起来相当笨拙,而且随着我们不断添加更多的不可变项,维护起来会非常困难
EDIT:我忘了提到布尔值被重构为变量以进行分析,实际上,存储在isDefined
中的表达式实际上在else if
语句中,因此会比此分析中显示的少10倍(我更关心的是平均执行时间,而不是绝对执行时间)。制作一个接口(例如,IImmutable
)并在所有不可变类上使用它
您只需使用typeof()
检查此接口即可检测不可变
typeof()
是一个编译时检查,因此没有性能影响。您使用的只定义在else
分支中,该分支的影响比then
分支小10倍。只在需要时计算该值。这将使其成本降低10倍
除此之外,您还可以为计算引入缓存。您可能检查过的类型很少,因此缓存会很小。我只缓存结果,因为类型的属性不会改变
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;
}
}
您可以将解决方案设置为通用的,我只是想知道这是一些快速的丑陋代码。尽管如此,这将有更好的性能。我最终实现了一个哈希集,该哈希集在静态构造函数中初始化,并获取我想要传递的所有类型
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);
}
}
}
}
感谢所有的帮助!我欢迎任何关于这个解决方案的想法我认为任何一个好的编译器都可以优化它(事实上,因为编译器应该知道System.Type是不可变的,它的方法没有副作用)…我很想在发行版中对其进行分析!感谢您的回答,我编辑了我的问题以澄清我确实这样做了,我只是对其进行了重构以使分析更容易。
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);
}
}
}
}
Type type = instance.GetType();
if (m_PassableTypes.Contains(type)) {
// cache the self-reference
referenceCache.Add(instance, instance);
// return the value itself
return instance;
}