Changeset 1322


Ignore:
Timestamp:
03/10/09 17:10:47 (10 years ago)
Author:
epitzer
Message:

cached cloning. (#506)

Location:
branches/New Persistence Exploration/Persistence/Persistence
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/New Persistence Exploration/Persistence/Persistence/NewSerializationTest.cs

    r1321 r1322  
    55using System.IO;
    66
    7 namespace Persistence {
     7namespace Persistence.Test {
    88
    99  public class Root {
    10 
    1110    [Storable]
    1211    public int[] i = new int[] { 3, 4, 5, 6 };
     
    4039    [Storable]
    4140    public string name = "Serial";
     41  }
     42
     43  public class CloneableRoot {
     44    public int[] i = new int[] { 3, 4, 5, 6 };
     45    public string s;
     46    public ArrayList intArray = new ArrayList(new int[] { 1, 2, 3 });
     47    public List<int> intList = new List<int>(new int[] { 321, 312, 321 });
     48    public CloneableCustom c;
     49    public List<CloneableRoot> selfReferences;
     50    public double[,] multiDimArray = new double[,] { { 1, 2, 3 }, { 3, 4, 5 } };
     51    public bool boolean = true;
     52    public DateTime dateTime = new DateTime();
     53    public KeyValuePair<string, int> kvp = new KeyValuePair<string, int>("test key", 123);
     54    public Dictionary<string, int> dict = new Dictionary<string, int>();   
     55    public object Clone(Dictionary<object, object> twins) {
     56      if (twins.ContainsKey(this))
     57        return twins[this];     
     58      CloneableRoot cr = new CloneableRoot();
     59      twins.Add(this, cr);
     60      cr.i = this.i;
     61      cr.s = this.s;
     62      cr.intArray = new ArrayList(this.intArray);
     63      cr.intList = new List<int>(this.intList);
     64      cr.c = (CloneableCustom)c.Clone(twins);
     65      cr.selfReferences = new List<CloneableRoot>();
     66      for (int i = 0; i < this.selfReferences.Count; i++) {
     67        cr.selfReferences.Add(this);
     68      }
     69      cr.multiDimArray = (double[,])this.multiDimArray.Clone();
     70      cr.dateTime = new DateTime(this.dateTime.Ticks);
     71      cr.kvp = new KeyValuePair<string, int>(this.kvp.Key, this.kvp.Value);
     72      cr.dict = new Dictionary<string, int>(this.dict);
     73      return cr;
     74    }   
     75  }
     76
     77  public class CloneableCustom {   
     78    public int i;   
     79    public CloneableRoot r;   
     80    public string name = "Serial";
     81    public object Clone(Dictionary<object, object> twins) {
     82      if (twins.ContainsKey(this))
     83        return twins[this];
     84      CloneableCustom cc = new CloneableCustom();
     85      twins.Add(this, cc);
     86      cc.i = this.i;
     87      cc.r = (CloneableRoot)this.r.Clone(twins);
     88      cc.name = this.name;
     89      return cc;
     90    }
    4291  }
    4392
     
    52101    [Storable]
    53102    private Nullable<double> dbl = null;
     103  }
     104
     105  public class StorableObject {
     106
     107    [Storable]
     108    Dictionary<int, string> dict;
     109
     110    public void Init() {
     111      this.dict = new Dictionary<int, string>();
     112      for (int i = 0; i < 1000000; i++) {
     113        dict.Add(i, i.ToString());
     114      }
     115    }
     116  }
     117
     118  public class CloneableObject : ICloneable {
     119
     120    Dictionary<int, string> dict;
     121
     122    public void Init() {
     123      this.dict = new Dictionary<int, string>();
     124      for (int i = 0; i < 1000000; i++) {
     125        dict.Add(i, i.ToString());
     126      }
     127    }
     128    public object Clone() {
     129      CloneableObject clone = new CloneableObject();
     130      clone.dict = new Dictionary<int, string>(this.dict);
     131      return clone;
     132    }
    54133  } 
    55134
     
    78157      DeSerializer deSerializer = new DeSerializer();       
    79158      object o = deSerializer.DeSerialize(parser);
    80       Root t = StorableAttribute.Clone(r);
     159      Root t = CloningFactory.DefaultClone(r);
    81160      Console.Out.WriteLine(Util.AutoFormat(o, true));     
    82161    }
     
    96175      DeSerializer deSerializer = new DeSerializer();
    97176      object o = deSerializer.DeSerialize(parser);
    98       Manager n = StorableAttribute.Clone(m);
     177      Manager n = CloningFactory.DefaultClone(m);
    99178      Console.Out.WriteLine(Util.AutoFormat(o, true));     
    100179    }
    101180
     181    public static void SpeedTest() {
     182      StorableObject storable = new StorableObject();
     183      CloneableObject cloneable = new CloneableObject();
     184      Console.Write("initializing...");
     185      storable.Init();
     186      cloneable.Init();
     187      Console.WriteLine("done");
     188      List<StorableObject> storableClones = new List<StorableObject>();
     189      List<CloneableObject> clonableClones = new List<CloneableObject>();
     190      CloningFactory cloningFactory = new CloningFactory();
     191      for (int i = 0; i < 100000; i++) {
     192        Console.Write("cloning storable.. ");
     193        storableClones.Add(cloningFactory.Clone(storable));
     194        Console.WriteLine();
     195        Console.Write("cloning cloneable.. ");
     196        clonableClones.Add((CloneableObject)cloneable.Clone());
     197        Console.WriteLine();
     198      }
     199    }
     200
     201    public static void SpeedTest2() {
     202      Root r = new Root();
     203      r.selfReferences = new List<Root>();
     204      r.selfReferences.Add(r);
     205      r.selfReferences.Add(r);
     206      r.c = new Custom();
     207      r.c.r = r;
     208      r.dict.Add("one", 1);
     209      r.dict.Add("two", 2);
     210      r.dict.Add("three", 3);
     211
     212      CloneableRoot cr = new CloneableRoot();
     213      cr.selfReferences = new List<CloneableRoot>();
     214      cr.selfReferences.Add(cr);
     215      cr.selfReferences.Add(cr);
     216      cr.c = new CloneableCustom();
     217      cr.c.r = cr;
     218      cr.dict.Add("one", 1);
     219      cr.dict.Add("two", 2);
     220      cr.dict.Add("three", 3);     
     221      List<Root> storableClones = new List<Root>();
     222      List<CloneableRoot> clonableClones = new List<CloneableRoot>();     
     223      CloningFactory cloningFactory = new CloningFactory();
     224
     225      DateTime start = DateTime.Now;
     226      Console.Write("cloning storable.. ");
     227      for (int i = 0; i < 100000; i++) {       
     228        storableClones.Add(cloningFactory.Clone(r));                       
     229      }
     230      Console.WriteLine(new TimeSpan(DateTime.Now.Ticks - start.Ticks));
     231
     232      start = DateTime.Now;
     233      Console.Write("cloning storable again.. ");
     234      for (int i = 0; i < 100000; i++) {
     235        storableClones.Add(cloningFactory.Clone(r));
     236      }
     237      Console.WriteLine(new TimeSpan(DateTime.Now.Ticks - start.Ticks));
     238
     239
     240      start = DateTime.Now;
     241      Console.Write("cloning cloneable.. ");
     242      for (int i = 0; i < 100000; i++) {       
     243        clonableClones.Add((CloneableRoot)cr.Clone(new Dictionary<object, object>()));
     244      }
     245      Console.WriteLine(new TimeSpan(DateTime.Now.Ticks - start.Ticks));
     246      clonableClones.Clear();
     247     
     248    }
     249
    102250    public static void Main() {
    103       Test1();
    104       Test2();
     251      //Test1();
     252      //Test2();
     253      //SpeedTest();
     254      SpeedTest2();
    105255      Console.In.ReadLine();
    106256    }
  • branches/New Persistence Exploration/Persistence/Persistence/Persistence.csproj

    r1281 r1322  
    1313    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    1414    <FileAlignment>512</FileAlignment>
    15     <StartupObject>Persistence.NewSerializationTest</StartupObject>
     15    <StartupObject>Persistence.Test.NewSerializationTest</StartupObject>
    1616  </PropertyGroup>
    1717  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
  • branches/New Persistence Exploration/Persistence/Persistence/StorableAttribute.cs

    r1321 r1322  
    4545      }
    4646      return autoStorableAccessors;
    47     }
    48 
    49     private static MethodInfo MemberwiseClone;
    50 
    51     public static StorableAttribute() {
    52       foreach (MethodInfo mi in typeof(object).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic)) {
    53         if (mi.Name == "MemberwiseClone") {
    54           MemberwiseClone = mi;
    55         }
    56       }
    57     }
    58 
    59     public static T Clone<T>(T obj) {
    60       List<ICompoundSerializer> compoundSerializers =
    61         InterfaceInstantiatior.InstantiateAll<ICompoundSerializer>();
    62       return Clone(obj, compoundSerializers);
    63     }
    64 
    65     public static T Clone<T>(T obj, IEnumerable<ICompoundSerializer> compoundSerializers) {
    66       Dictionary<object, object> twins = new Dictionary<object, object>();     
    67       return Clone(obj, twins, compoundSerializers);
    6847    }   
    69 
    70     public static T Clone<T>(T obj, Dictionary<object, object> twins,
    71       IEnumerable<ICompoundSerializer> compoundSerializers) {
     48  }
     49
     50  class CloningFactory {
     51
     52    private static CloningFactory instance = new CloningFactory();
     53
     54    public static T DefaultClone<T>(T obj) {
     55      return instance.Clone(obj);
     56    }
     57
     58    private List<ICompoundSerializer> compoundSerializers;
     59
     60    public CloningFactory(IEnumerable<ICompoundSerializer> compoundSerializers) {
     61      this.compoundSerializers = new List<ICompoundSerializer>(compoundSerializers);
     62    }
     63
     64    public CloningFactory() :
     65      this(InterfaceInstantiatior.InstantiateAll<ICompoundSerializer>()) { }
     66
     67    delegate object CloneMethod(object obj, Dictionary<object, object> twins);
     68
     69    Dictionary<Type, CloneMethod> cloneMethods = new Dictionary<Type, CloneMethod>();
     70
     71    public T Clone<T>(T obj) {
     72      Dictionary<object, object> twins = new Dictionary<object, object>();
     73      return Clone(obj, twins);
     74    }
     75
     76    public T Clone<T>(T obj, Dictionary<object, object> twins) {
    7277      if (obj == null)
    7378        return default(T);
     79
    7480      ValueType t = obj as ValueType;
    75       if (t != null) {
     81      if (t != null)
    7682        return (T)obj;
    77       }
     83
    7884      if (twins.ContainsKey(obj))
    7985        return (T)twins[obj];
     86
    8087      ICloneable c = obj as ICloneable;
    8188      if (c != null) {
    82         T newClone = (T)c.Clone();     
     89        T newClone = (T)c.Clone();
    8390        twins[obj] = newClone;
    8491        return newClone;
    8592      }
    86       T newInstance = (T)Activator.CreateInstance(obj.GetType());
    87       twins[obj] = newInstance;
    88       Dictionary<string, DataMemberAccessor> oldAccessors = GetAutostorableAccessors(obj);
    89       if (oldAccessors.Count == 0) {       
    90         foreach (ICompoundSerializer serializer in compoundSerializers) {
    91           if ( serializer.CanSerialize(obj.GetType()) ) {
    92             IEnumerable subObjects = serializer.Serialize(obj);
    93             IEnumerable clonedSubObjects = Functional.Map(subObjects,
    94               (x) => Clone(x, twins, compoundSerializers));
    95             return (T)serializer.DeSerialize(clonedSubObjects, obj.GetType());
     93
     94      Type type = obj.GetType();
     95      if (!cloneMethods.ContainsKey(type))
     96        cloneMethods[type] = CreateCloneMethod(type);
     97      return (T)cloneMethods[type](obj, twins);
     98    }
     99
     100    private CloneMethod CreateCloneMethod(Type type) {
     101      if (type.GetConstructor(new Type[] { type }) != null)
     102        return CopyConstructorCloneMethod.Create(type);
     103      foreach (ICompoundSerializer serializer in compoundSerializers)
     104        if (serializer.CanSerialize(type))
     105          return CompoundSerializerCloneMethod.Create(serializer, type, this);
     106      return StorableAccessorCloneMethod.Create(type, this);     
     107    }
     108
     109    class CopyConstructorCloneMethod {
     110      public static CloneMethod Create(Type type) {
     111        return new CopyConstructorCloneMethod(type).method;
     112      }
     113      private ConstructorInfo constructorInfo;
     114      public CopyConstructorCloneMethod(Type type) {
     115        this.constructorInfo = type.GetConstructor(new Type[] { type });
     116      }
     117
     118      object method(object obj, Dictionary<object, object> twins) {
     119        object newInstance = constructorInfo.Invoke(new object[] { obj });
     120        twins.Add(obj, newInstance);
     121        return newInstance;
     122      }
     123    }
     124
     125    class CompoundSerializerCloneMethod {
     126      public static CloneMethod Create(ICompoundSerializer serializer,
     127          Type type, CloningFactory factory) {
     128        return new CompoundSerializerCloneMethod(serializer, type, factory).method;
     129      }
     130      private ICompoundSerializer serializer;
     131      private Type type;
     132      private CloningFactory factory;
     133      public CompoundSerializerCloneMethod(ICompoundSerializer serializer,
     134          Type type, CloningFactory factory) {
     135        this.serializer = serializer;
     136        this.type = type;
     137        this.factory = factory;
     138      }
     139      object method(object obj, Dictionary<object, object> twins) {
     140        return serializer.DeSerialize(
     141          Functional.Map(
     142            serializer.Serialize(obj),
     143            (o) => factory.Clone(o, twins)),
     144          type);
     145      }
     146    }
     147
     148    class StorableAccessorCloneMethod {
     149
     150      delegate object Getter(object target);
     151      delegate void Setter(object target, object value);
     152
     153      struct FieldAccessor {     
     154        public Getter Getter;
     155        public Setter Setter;
     156        public FieldAccessor(Getter getter, Setter setter) {
     157          this.Getter = getter;
     158          this.Setter = setter;
     159        }
     160      }
     161
     162      private const BindingFlags INSTANCE_MEMBERS =
     163        BindingFlags.Instance |
     164        BindingFlags.Public |
     165        BindingFlags.NonPublic;
     166
     167      public static CloneMethod Create(Type type, CloningFactory factory) {
     168        return new StorableAccessorCloneMethod(type, factory).method;
     169      }
     170
     171      private List<FieldAccessor> fieldAccessors;
     172      private CloningFactory factory;
     173         
     174      public StorableAccessorCloneMethod(Type type, CloningFactory factory) {
     175        this.factory = factory;
     176        this.fieldAccessors = new List<FieldAccessor>();
     177        foreach (MemberInfo memberInfo in type.GetMembers(INSTANCE_MEMBERS)) {
     178          foreach (object attribute in memberInfo.GetCustomAttributes(false)) {
     179            StorableAttribute autoStorableAttribute =
     180              attribute as StorableAttribute;
     181            if (autoStorableAttribute != null) {
     182              if (memberInfo.MemberType == MemberTypes.Field) {
     183                FieldInfo fi = (FieldInfo)memberInfo;
     184                fieldAccessors.Add(new FieldAccessor(
     185                  fi.GetValue,
     186                  fi.SetValue));
     187              } else if (memberInfo.MemberType == MemberTypes.Property) {
     188                PropertyInfo pi = (PropertyInfo)memberInfo;
     189                fieldAccessors.Add(new FieldAccessor(
     190                  (target) => pi.GetValue(target, null),
     191                  (target, value) => pi.SetValue(target, value, null)));
     192              }
     193            }
    96194          }
    97195        }
    98         // TODO: fallback with memberwise clone?
    99         throw new ApplicationException("cannot continue cloning, reached a dead end");
    100       }
    101       Dictionary<string, DataMemberAccessor> newAccessors = GetAutostorableAccessors(newInstance);
    102       foreach (KeyValuePair<string, DataMemberAccessor> nameAccess in oldAccessors) {
    103         newAccessors[nameAccess.Key].Set(Clone(nameAccess.Value.Get(), twins, compoundSerializers));
    104       }
    105       return newInstance;
     196      }
     197      object method(object obj, Dictionary<object, object> twins) {
     198        object newInstance = Activator.CreateInstance(obj.GetType());
     199        twins.Add(obj, newInstance);
     200        foreach (FieldAccessor fa in this.fieldAccessors) {
     201          fa.Setter(newInstance, factory.Clone(fa.Getter(obj), twins));
     202        }
     203        return newInstance;
     204      }
    106205    }
    107206  }
    108 
     207 
    109208  public interface IDataMemberAccessor {
    110209    string Name { get; }
     
    200299  }
    201300
    202 
    203  
    204 
    205301}
Note: See TracChangeset for help on using the changeset viewer.