Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
04/28/10 11:33:38 (15 years ago)
Author:
epitzer
Message:

replace repeated calls through reflection with generated code for a twofold speedup (#548)

Location:
trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableReflection.cs

    r3205 r3553  
    77using HeuristicLab.Persistence.Auxiliary;
    88using System.Text;
     9using System.Reflection.Emit;
    910
    1011namespace HeuristicLab.Persistence.Default.CompositeSerializers.Storable {
     
    1819      BindingFlags.DeclaredOnly;
    1920
    20     public static IEnumerable<StorableMemberInfo> GenerateStorableMembers(Type type, bool inherited) {
     21    private delegate void HookWrapper<T>(T o);
     22    public delegate void Hook(object o);
     23
     24    public static IEnumerable<StorableMemberInfo> GenerateStorableMembers(Type type) {
    2125      var storableMembers = new List<StorableMemberInfo>();
    22       if (inherited && type.BaseType != null)
    23         storableMembers.AddRange(GenerateStorableMembers(type.BaseType, true));
     26      if (type.BaseType != null)
     27        storableMembers.AddRange(GenerateStorableMembers(type.BaseType));
    2428
    2529      var storableClassAttribute = GetStorableClassAttribute(type);
     
    4751    }
    4852
    49     public static IEnumerable<MethodInfo> CollectHooks(HookType hookType, Type type) {
     53    public static IEnumerable<Hook> CollectHooks(HookType hookType, Type type) {
    5054      if (type.BaseType != null)
    5155        foreach (var mi in CollectHooks(hookType, type.BaseType))
     
    5660            MethodInfo methodInfo = memberInfo as MethodInfo;
    5761            if (memberInfo.MemberType != MemberTypes.Method || memberInfo == null)
    58               throw new ArgumentException("Storable hooks must be methods");
    59             yield return methodInfo;
     62              throw new ArgumentException("Storable hooks must be methods");       
     63            DynamicMethod dm = new DynamicMethod("", null, new[] { typeof(object) }, type);
     64            ILGenerator ilgen = dm.GetILGenerator();
     65            ilgen.Emit(OpCodes.Ldarg_1);
     66            ilgen.Emit(OpCodes.Call, methodInfo);
     67            ilgen.Emit(OpCodes.Ret);
     68            yield return (Hook)dm.CreateDelegate(typeof(Hook));
    6069          }
    6170        }
  • trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Storable/StorableSerializer.cs

    r3036 r3553  
    77using HeuristicLab.Persistence.Auxiliary;
    88using System.Text;
     9using System.Reflection.Emit;
    910
    1011namespace HeuristicLab.Persistence.Default.CompositeSerializers.Storable {
     
    3839    /// </returns>
    3940    public bool CanSerialize(Type type) {
    40       if (!ReflectionTools.HasDefaultConstructor(type) &&
    41         GetStorableConstructor(type) == null)
     41      if (GetConstructor(type) == null)
    4242        return false;
    4343      return StorableReflection.IsEmptyOrStorableType(type, true);
     
    5353    /// </returns>
    5454    public string JustifyRejection(Type type) {
    55       if (!ReflectionTools.HasDefaultConstructor(type) &&
    56         GetStorableConstructor(type) == null)
     55      if (GetConstructor(type) == null)
    5756        return "no default constructor and no storable constructor";
    5857      if (!StorableReflection.IsEmptyOrStorableType(type, true))
     
    8483    }
    8584
    86     private static readonly object[] defaultArgs = new object[] { true };
    87 
    8885    /// <summary>
    8986    /// Create an instance of the object using the provided meta information.
     
    9491    public object CreateInstance(Type type, IEnumerable<Tag> metaInfo) {
    9592      try {
    96         ConstructorInfo constructor = GetStorableConstructor(type);
    97         return constructor != null ? constructor.Invoke(defaultArgs) : Activator.CreateInstance(type, true);
     93        return GetConstructor(type)();
    9894      } catch (TargetInvocationException x) {
    9995        throw new PersistenceException(
     
    134130    private static readonly object[] emptyArgs = new object[] { };
    135131
    136     private sealed class TypeQuery {
     132    private sealed class HookDesignator {
    137133      public Type Type { get; private set; }
    138       public bool Inherited { get; private set; }
    139       public TypeQuery(Type type, bool inherited) {
    140         this.Type = type;
    141         this.Inherited = inherited;
    142       }
    143     }
    144 
    145     private sealed class HookDesignator {
    146       public Type Type { get; set; }
    147       public HookType HookType { get; set; }
     134      public HookType HookType { get; private set; }
    148135      public HookDesignator() { }
    149136      public HookDesignator(Type type, HookType hookType) {
     
    153140    }
    154141
    155     private sealed class MemberCache : Dictionary<TypeQuery, IEnumerable<StorableMemberInfo>> { }
     142    private sealed class MemberCache : Dictionary<Type, IEnumerable<StorableMemberInfo>> { }
    156143
    157144    #endregion
     
    160147
    161148    private MemberCache storableMemberCache = new MemberCache();
    162     private Dictionary<Type, ConstructorInfo> constructorCache =
    163       new Dictionary<Type, ConstructorInfo>();
    164    
    165     private Dictionary<HookDesignator, List<MethodInfo>> hookCache =
    166       new Dictionary<HookDesignator, List<MethodInfo>>();
     149
     150    private delegate object Constructor();
     151
     152    private Dictionary<Type, Constructor> constructorCache =
     153      new Dictionary<Type, Constructor>();
     154
     155    private Dictionary<HookDesignator, List<StorableReflection.Hook>> hookCache =
     156      new Dictionary<HookDesignator, List<StorableReflection.Hook>>();
    167157
    168158    #endregion
     
    171161
    172162    private IEnumerable<StorableMemberInfo> GetStorableMembers(Type type) {
    173       return GetStorableMembers(type, true);
    174     }
    175 
    176     private IEnumerable<StorableMemberInfo> GetStorableMembers(Type type, bool inherited) {
    177163      lock (storableMemberCache) {
    178         var query = new TypeQuery(type, inherited);
    179         if (storableMemberCache.ContainsKey(query))
    180           return storableMemberCache[query];
    181         var storablesMembers = StorableReflection.GenerateStorableMembers(type, inherited);
    182         storableMemberCache[query] = storablesMembers;
     164        if (storableMemberCache.ContainsKey(type))
     165          return storableMemberCache[type];
     166        var storablesMembers = StorableReflection.GenerateStorableMembers(type);
     167        storableMemberCache[type] = storablesMembers;
    183168        return storablesMembers;
    184169      }
    185     }   
    186 
    187     private ConstructorInfo GetStorableConstructor(Type type) {
     170    }
     171
     172    private Constructor GetConstructor(Type type) {
    188173      lock (constructorCache) {
    189174        if (constructorCache.ContainsKey(type))
    190175          return constructorCache[type];
    191         foreach (ConstructorInfo ci in type.GetConstructors(ALL_CONSTRUCTORS)) {
    192           if (ci.GetCustomAttributes(typeof(StorableConstructorAttribute), false).Length > 0) {
    193             if (ci.GetParameters().Length != 1 ||
    194                 ci.GetParameters()[0].ParameterType != typeof(bool))
    195               throw new PersistenceException("StorableConstructor must have exactly one argument of type bool");
    196             constructorCache[type] = ci;
    197             return ci;
    198           }
     176        Constructor c = FindStorableConstructor(type) ?? GetDefaultConstructor(type);
     177        constructorCache.Add(type, c);
     178        return c;
     179      }
     180    }
     181
     182    private Constructor GetDefaultConstructor(Type type) {
     183      ConstructorInfo ci = type.GetConstructor(ALL_CONSTRUCTORS, null, Type.EmptyTypes, null);
     184      if (ci == null)
     185        return null;
     186      DynamicMethod dm = new DynamicMethod("", typeof(object), null, type);
     187      ILGenerator ilgen = dm.GetILGenerator();
     188      ilgen.Emit(OpCodes.Newobj, ci);
     189      ilgen.Emit(OpCodes.Ret);
     190      return (Constructor)dm.CreateDelegate(typeof(Constructor));
     191    }
     192
     193    private Constructor FindStorableConstructor(Type type) {
     194      foreach (ConstructorInfo ci in type.GetConstructors(ALL_CONSTRUCTORS)) {
     195        if (ci.GetCustomAttributes(typeof(StorableConstructorAttribute), false).Length > 0) {
     196          if (ci.GetParameters().Length != 1 ||
     197              ci.GetParameters()[0].ParameterType != typeof(bool))
     198            throw new PersistenceException("StorableConstructor must have exactly one argument of type bool");
     199          DynamicMethod dm = new DynamicMethod("", typeof(object), null, type);
     200          ILGenerator ilgen = dm.GetILGenerator();
     201          ilgen.Emit(OpCodes.Ldc_I4_1); // load true
     202          ilgen.Emit(OpCodes.Newobj, ci);
     203          ilgen.Emit(OpCodes.Ret);
     204          return (Constructor)dm.CreateDelegate(typeof(Constructor));
    199205        }
    200         constructorCache[type] = null;
    201         return null;
    202       }
     206      }
     207      return null;
    203208    }
    204209
     
    211216      if (obj == null)
    212217        throw new ArgumentNullException("Cannot invoke hooks on null");
    213       foreach (MethodInfo mi in GetHooks(hookType, obj.GetType())) {
    214         mi.Invoke(obj, emptyArgs);
    215       }
    216     }
    217 
    218     private IEnumerable<MethodInfo> GetHooks(HookType hookType, Type type) {
     218      foreach (StorableReflection.Hook hook in GetHooks(hookType, obj.GetType())) {
     219        hook(obj);
     220      }
     221    }
     222
     223    private IEnumerable<StorableReflection.Hook> GetHooks(HookType hookType, Type type) {
    219224      lock (hookCache) {
    220         List<MethodInfo> hooks;
     225        List<StorableReflection.Hook> hooks;
    221226        var designator = new HookDesignator(type, hookType);
    222227        hookCache.TryGetValue(designator, out hooks);
    223228        if (hooks != null)
    224229          return hooks;
    225         hooks = new List<MethodInfo>(StorableReflection.CollectHooks(hookType, type));
     230        hooks = new List<StorableReflection.Hook>(StorableReflection.CollectHooks(hookType, type));
    226231        hookCache.Add(designator, hooks);
    227232        return hooks;
     
    231236    #endregion
    232237
    233    
    234    
     238
     239
    235240  }
    236  
     241
    237242}
Note: See TracChangeset for help on using the changeset viewer.