Fast cloning method

I am trying to optimize a piece of code that clones an object:

#region ICloneable public object Clone() { MemoryStream buffer = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(buffer, this); // takes 3.2 seconds buffer.Position = 0; return formatter.Deserialize(buffer); // takes 2.1 seconds } #endregion 

Pretty standard stuff. The problem is that the object is quite soft and takes 5.4 seconds (according to the ANTS Profiler - I'm sure the profiler overhead, but still).

Is there a better and faster way to clone?

+4
source share
5 answers
  • Do not implement ICloneable.

  • A quick way to clone an object is to create a new instance of the same type and copy / clone all the fields from the original instance to the new instance. Do not try to come up with a β€œgeneral” cloning method that can clone any object of any class.

Example:

 class Person { private string firstname; private string lastname; private int age; public Person(string firstname, string lastname, int age) { this.firstname = firstname; this.lastname = lastname; this.age = age; } public Person Clone() { return new Person(this.firstname, this.lastname, this.age); } } 
+6
source

As I understand it, streams, even internal ones like this, are expensive. Did you try to just create a new object and update the corresponding fields to bring the object into the same state? I find it hard to believe that your method takes less time.

+1
source

This is a fairly expensive way to clone. The object never gets on the wire, so all the time serialization is mostly lost. This will be faster than making a cloned member. I understand that this is not an automatic solution, but it will be the fastest.

Something like that:

 class SuperDuperClassWithLotsAndLotsOfProperties { object Clone() { return new SuperDuperClassWithLotsAndLotsOfProperties { Property1 = Property1, Property2 = Property2, } public string Property1 {get;set;} public string Property2 {get;set;} } } 
+1
source

Since manually copying fields is the fastest way to create a code generator that reads the definition of your class and generates a cloning method. All you need is a CGbR nuget package and an incomplete class that implements ICloneable . The generator will do the rest.

 public partial class Root : ICloneable { public Root(int number) { _number = number; } private int _number; public Partial[] Partials { get; set; } public IList<ulong> Numbers { get; set; } public object Clone() { return Clone(true); } private Root() { } } public partial class Root { public Root Clone(bool deep) { var copy = new Root(); // All value types can be simply copied copy._number = _number; if (deep) { // In a deep clone the references are cloned var tempPartials = new Partial[Partials.Length]; for (var i = 0; i < Partials.Length; i++) { var value = Partials[i]; value = value.Clone(true); tempPartials[i] = value; } copy.Partials = tempPartials; var tempNumbers = new List<ulong>(Numbers.Count); for (var i = 0; i < Numbers.Count; i++) { var value = Numbers[i]; tempNumbers[i] = value; } copy.Numbers = tempNumbers; } else { // In a shallow clone only references are copied copy.Partials = Partials; copy.Numbers = Numbers; } return copy; } } 

And partial class

 public partial class Partial : ICloneable { public short Id { get; set; } public string Name { get; set; } public object Clone() { return Clone(true); } } public partial class Partial { public Partial Clone(bool deep) { var copy = new Partial(); // All value types can be simply copied copy.Id = Id; copy.Name = Name; return copy; } } 
+1
source

Answer: There are better cloning methods.

Reflection or expression Trees are much faster than serialization (reflection is 5 times faster , expression trees are 20 times faster ).

enter image description here

If you use this related cloning function as an extension method, each of your cloning code is compressed to

 #region ICloneable public object Clone() { return this.DeepCopyByExpressionTree(); } #endregion 

To use the extension method, just have the DeepCopyByExptressionTrees.cs file anywhere in your solution.

0
source

Source: https://habr.com/ru/post/1309060/


All Articles