0

Just started learning C#, I was testing any performance difference between passing an arguement to a method using in modifier and without it. So I wrote the code below which is behaving quite strangely,

class Program
{
    static void Main(string[] args)
    {
        int n=5;
        float sum=0;
        for(int i=1; i<=n; i++){
            sum+=VectorPerfGain();
            Thread.Sleep(200);
        }
        Console.WriteLine("Avg Performance Gain Ref/Normal="+sum/5+"%");
    }

    static float VectorPerfGain()
    {
        float t_ref, t_normal;
        List<Vector> vectors;
        Stopwatch watch;
        
        //--------------------------------------BLOCK-A---------------------------//

        vectors=new List<Vector>(){
            new Vector(67.3,34.2), new Vector(38.3,98.12)
        };
        watch=Stopwatch.StartNew();
        for(int i=1; i<10000000; i++){
            vectors.Add(Vector.GetNew(vectors[vectors.Count-1],vectors[vectors.Count-2]));
        }
        watch.Stop();
        t_normal=watch.ElapsedMilliseconds;

        
        //--------------------------------------BLOCK-B---------------------------//

        vectors=new List<Vector>(){
            new Vector(67.3,34.2), new Vector(38.3,98.12)
        };
        watch=Stopwatch.StartNew();
        for(int i=1; i<10000000; i++){
            vectors.Add(Vector.GetNewByRef(vectors[vectors.Count-1],vectors[vectors.Count-2]));
        }
        watch.Stop();
        t_ref=watch.ElapsedMilliseconds;
        
        return (t_normal-t_ref)*100/t_normal;
    }
    
    struct Vector{
        public double x, y;

        public Vector(double x, double y){ this.x=x; this.y=y; }

        public static Vector GetNew(Vector a, Vector b)
        {
            return new Vector(a.x+b.x,a.y+b.y);
        }

        public static Vector GetNewByRef(in Vector a, in Vector b)
        {
            return new Vector(a.x+b.x,a.y+b.y);
        }
    }
}

I am measuring the percentage of performance gain by calling the Vector.GetNewByRef() with respect to the Vector.GetNew() method.

When I run the code above I get on average about -0.5% performance gain with about 1-2% fluctuation.

Now when I move BLOCK-B before BLOCK-A in VectorPerfGain() the average performance gain jumps to -28% with 3-4% fluctuation!

Wait there' more.

When I change struct Vector to class Vector and run using BLOCK-A before BLOCK-B the average performance gain is -21% with 2-3% fluctuation (i.e. the opposite of what happened when Vector was a struct).

Then when I run the code putting BLOCK-B before BLOCK-A the performance fluctuates widely from 5-25% (note this time it is positive), so average value is not reliable here.

The most important question I have is why simply changing the order of two code blocks which are independent of each other would change the result so drastically?

  • 6
    If you're running benchmarks, use [BenchmarkDotNet](https://benchmarkdotnet.org). There are many variables when benchmarking and you're not controlling for them. If you can repeat your observations using BenchmarkDotNet, then we'll take a look at them. – canton7 Feb 22 '22 at 14:05
  • 2
    The Garbage Collector says "hi", I guess. – Matthew Watson Feb 22 '22 at 14:17

0 Answers0