Performant way to detect immutables?

谁说胖子不能爱 提交于 2019-12-05 17:28:52

Make an interface (eg. IImmutable) and use it on all your immutable classes.

You only have to check for this interface with typeof() to detect an immutable.

typeof() is a compile time check, so you have no performance hit.

You are using isDefined only in the else branch which is hit 10x less then the then branch. Only compute the value when needed. That should cut its cost by 10x.

Apart from that you could introduce a cache for the computation. There are probably very few types that you ever inspect, so the cache would be small.

I'd just cache the result since type's attributes are not going to change.

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

Then use

bool isDefined = SomeHelperClass.IsMessageAttributeDefined(type);

You may make the solution generic, I just give some idea this is some quick ugly code. This will be better performing though.

I ended up implementing a Hash set that is initialized in the static constructor and gets all the type I want to pass trough.

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

This allows me to then perform a really fast HashSet look up which is way more performant.

    Type type = instance.GetType();

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

Thanks for all the help! I'd welcome any thoughts on this solution

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!