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 pretty beefy and it takes 5.4 seconds (according ANTS Profiler - I am sure there is the profiler overhead, but still).
Is there a better and faster way to clone?
-
Don't implement ICloneable.
The fast way to clone an object is to create a new instance of the same type and copy/clone all fields from the original instance to the new instance. Don't try to come up with a "generic" clone 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); } }Aaronaught : I agree. I'd also like to add an option (3), use an immutable type so that you don't *need* to clone. -
As I understand it, streams, even inner ones like this, are expensive.
Have you tried to just create a new object it and update the relevant fields to bring the object to the same state? I find it hard to believe your method takes less time.Guffa : It's rather the reflection used to do the serialisation and deserialisation that is expensive. -
That's a pretty expensive way to clone. The object never gets on the wire, so all the time doing serialisation is basically wasted. It will be way faster to do memberwise clone. I realise it's not an automagic solution, but it'll be the fastest.
Something along these lines:
class SuperDuperClassWithLotsAndLotsOfProperties { object Clone() { return new SuperDuperClassWithLotsAndLotsOfProperties { Property1 = Property1, Property2 = Property2, } public string Property1 {get;set;} public string Property2 {get;set;} } }
0 comments:
Post a Comment