开发者

Clone with better performance

I want to create deep copy method an开发者_如何转开发d I found 3 ways to execute it

1-deep copy with pass each property 1 by 1

2-using reflection

3-using serialization

please which of them is the best at performance wise


I made graph with comparison of the three methods plus an expression trees method.

Clone with better performance

For large number of objects is reflection 5x faster and manual code and expression trees are 20x faster than serialization. The best by performance are therefore manual code and expression trees.

Links to used cloning codes (2.-4. used as an extension method):

  1. Manual: Written manually, no link.
  2. Cloning by Serialization
  3. Cloning by Reflection
  4. Cloning by Expression Trees


The first option, manually deep copying your values, will be the most performant by far.

Reflection will introduce quite a bit of overhead, as it is (relatively) slow to access data.

Serialization is adding a huge cost, as it serializes the data into a temporary structure, then reverses the process to set. This is again, very slow.

The only advantage to option 2 or 3 is that its potentially easier to implement, and reusable across multiple types. The first option has to be hand-written per type, but is much faster (and more efficient in memory usage than option 3, as well).


Order you listed your possible solutions is correct performance order.

You will get best performance when you write the code to clone each property value manually.

Reflection will have similar result as manually cloning but little slower.

Serialization is the worst scenario. But quickest to implement.

Here is a good article that describes other possible solutions.

So here is a list of all possible cloning methods:

  1. Clone Manually
  2. Clone with MemberwiseClone
  3. Clone with Reflection
  4. Clone with Serialization
  5. Clone with IL
  6. Clone with Extension Methods

Me personally would go with "Clone with IL" as it is slightly faster than reflection and you don't have to clone everything manually.


The best for performance is creating the clone in your code. So the way "1".


There's the ICloneable interface. If cloning something ICloneable, using its methods would be best solution


Sounds like you've done the hard work of finding the ways to do it, so now you'll have to test them all in your specific situation and find out.

For the most part, it really depends on what data you're serializing


Reflection can be use to produce DynamicMethod which can be more efficient than manually copy (auto-properties can be copied by accessing fields directly breaking scope via skipVisibilityCheck). DynamicMethod offer you a delegate you can keep in static readonly field to clone your object. This is the fast and easy way to do it but not forcely the cleanest. Serialization is slow and not adapted.


As the author of CGbR I would like to invite you to give it a try for your use case.

All you need is the nuget package and a partial class definition that implements ICloneable. The generated will then create a file next to it with a Clone(bool deep) method.

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

Performance: In a benchmark for a clone we needed at work the compared it to DataContractSerializer and MemoryStream. The generated code is 600x faster.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜