Difference between copying reference of a class and copying value

Viewed 535

For an experiment, I tried this :

(1) Create 100000 classes, each of them wrapping a double variable

---This is the experiment part---

(2) Measured performance of two methods by running 100000 times :

  • create a double[] and assign the value of wrapped variables.

  • create a class[] and assign the reference of wrapping class.

The above may confuse you, so I am attaching the code :

static void Main(string[] args)
{
    int length = 100000;
    Test test = new Test(length);

    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();

    for (int i = 0; i < length; i++)
        test.CopyValue();
        //test.CopyReference(); //test.CopyValue(); or test.CopyReference();

    stopwatch.Stop();
    Console.WriteLine("RunTime : {0} ", stopwatch.ElapsedMilliseconds);
}

class DoubleWrapper
{
    public double value = 0.0;
}

class Test
{
    DoubleWrapper[] wrapper;

    public void CopyValue()
    {
        double[] x = new double[wrapper.Length];
        for (int i = 0; i < wrapper.Length; i++)
            x[i] = wrapper[i].value;
    }

    public void CopyReference()
    {
        DoubleWrapper[] x = new DoubleWrapper[wrapper.Length];
        for (int i = 0; i < wrapper.Length; i++)
            x[i] = wrapper[i];
    }

    public Test(int length)
    {
        wrapper = new DoubleWrapper[length];
        for (int i = 0; i < length; i++)
            wrapper[i] = new DoubleWrapper();
    }
}

The result is as follows :

test.CopyValue() : 56890 (millisec)

test.CopyReference() : 66688 (millisec)

(built with release configuration and ran exe)

I tried several times, but the result doesn't change much. So I concluded that CopyReference() takes longer time.


But I hardly understand why. Here is the question :

I thought that, regardless of CopyValue() or CopyReference(), what my machine does is "Copying a number in memory" though one is double value and the another is reference to a class. So there should not be meaningful difference in performance, but the fact is not.

Then what is the difference between copying a value and copying a reference? Does copying a reference do more thing than copying a value?

(When passing a reference without ref keyword, isn't it true that reference is copied as if it were value? What I am saying is that,

ClassA x = new ClassA();
ClassA y = x;

means making a copy of "reference of x" and then assigning to variable y, consequently y = null doesn't affect x at all. Is this true?)

If I am working with wrong assumptions, please let me know what I am wrong with.

I appreciate your help and advice.

-

I guessed that GC might have some impact, but turning off GC by TryStartNoGCRegion(Int64) doesn't change the conclusion. (both become faster, but still CopyReference() is slower.)

2 Answers

means making a copy of "reference of x" and then assigning to variable y, consequently y = null doesn't affect x at all. Is this true?

That's correct - you made a copy of reference.

Now, what about why your implementation of CopyReference is slower.

You have to do performance analysis to get real insight about it, but on top of my head:

You're creating a new instance of DoubleWrapper reference type, inside that method. Remember, that C# is not "zero-cost abstraction" language, like C/C++/Rust might be. Creating an instance of, even simple reference type, that does nothing more than a simple wrapper over a primitive type, suppose to cost you more. Because that instance has more in it than a simple double value - the size of DoubleWrapperobject will not be equal to 8 bytes.

Reading about the stack and the heap may help you understand. if you copy a reference, you essentially copy the pointer showing to the actual object in the heap, and if that actual object changes, those changes are shown on every thing that references that object.

If you do a "deep copy", or a clone (like when implementing IClonable) you will duplicate that data in the stack and create a pointer to it, thus not beeing dependant on the original object any longer.

I hope this explanation helps you a little bit? See this for some information https://www.c-sharpcorner.com/article/C-Sharp-heaping-vs-stacking-in-net-part-i/ on the stack and heap.

Related