samedi 29 février 2020

What is the advantage of using structs for UOMs like Temperature?

I ran the code below to test speed of some common uses in my program for UOM's and was quite surprised. With the results: All tests were run 1 million times in debug mode (run mode gave similar differences). It seems there is no real advantage in using structs for UOMs from a speed point of view so can anyone tell what any advantages would be? (I have a big number crunching program and this is of huge interest to me). If the example code is wrong in any way below, please let me know also. What I really want is the most convenient way to handle UOMs without making the code verbose (UOM * UOM rather than UOM.Value * UOM.Value would be best but its apparently not the most speed efficient). All times in ms.

Multply doubles 7

Multply struct fields 8

Multply struct property 232

Multply temperature struct using overloaded * operator 141

Multply class fields 7

Multiply & Load doubles into object array 692

Multiply struct fields & Load into object array 719

Multiply struct fields & Load new struct into object array 926

Multiply structs with overloaded operator a load struct into object array 906

Multiply class fields & load into object array 697

Multiply class fields & load new class into object array 964

Multiply class using overloaded * operator & load class into object array 948

public class TestSpeed
{
    public class TempClass
    {
        public double value=100;
        private double v;

        public TempClass(double v)
        {
            this.v = v;
        }

        public static TempClass operator *(TempClass t1, TempClass t2)
        {
            return new TempClass(t1.value * t2.value);
        }
    }

    public struct TempStruct
    {
        public double value;

        public TempStruct(double v)
        {
            value = v;
        }

        public double GetTemp
        {
            get { return value; }
            set { this.value = value; }
        }

        public static TempStruct operator *(TempStruct t1, TempStruct t2)
        {
            return new TempStruct(t1.value * t2.value);
        }
    }


    [TestMethod]
    public void TestDouble()
    {
        double doubleValue = 100;
        TempStruct t = new TempStruct();
        TempStruct Tres= new TempStruct(100);
        TempClass tclass = new TempClass(100);
        double res;

        var watch = Stopwatch.StartNew();

        for (int i = 0; i < 10000000; i++)
        {
            res = doubleValue*doubleValue;
        }

        watch.Stop();

        var elapsedMs = watch.ElapsedMilliseconds;
        Debug.WriteLine("Multply doubles "+ elapsedMs.ToString());

        watch = Stopwatch.StartNew();

        for (int i = 0; i < 10000000; i++)
        {
            Tres.value = t.value * t.value;
        }

        watch.Stop();


        elapsedMs = watch.ElapsedMilliseconds;
        Debug.WriteLine("Multply struct fields " + elapsedMs.ToString());

        watch = Stopwatch.StartNew();

        for (int i = 0; i < 10000000; i++)
        {
            Tres.GetTemp = t.GetTemp * t.GetTemp;
        }

        watch.Stop();


        elapsedMs = watch.ElapsedMilliseconds;
        Debug.WriteLine("Multply struct property " + elapsedMs.ToString());


        watch = Stopwatch.StartNew();

        for (int i = 0; i < 10000000; i++)
        {
            Tres = t * t;
        }

        watch.Stop();

        elapsedMs = watch.ElapsedMilliseconds;
        Debug.WriteLine("Multply temperature struct using overloaded * operator " + elapsedMs.ToString());

        watch = Stopwatch.StartNew();

        for (int i = 0; i < 10000000; i++)
        {
            res = tclass.value * tclass.value;
        }

        watch.Stop();
        elapsedMs = watch.ElapsedMilliseconds;
        Debug.WriteLine("Multply class fields " + elapsedMs.ToString());
    }


    [TestMethod]
    public void TestDoubleArray()
    {
        double doublevalue = 100;
        TempStruct t = new TempStruct();
        TempStruct Tres = new TempStruct(100);
        TempClass tclass = new TempClass(100);
        object[] res = new object[10000000];

        var watch = Stopwatch.StartNew();

        for (int i = 0; i < 10000000; i++)
        {
            res[i] = doublevalue * doublevalue;
        }

        watch.Stop();

        var elapsedMs = watch.ElapsedMilliseconds;
        Debug.WriteLine("Multiply & Load doubles into object array " + elapsedMs.ToString());

        watch = Stopwatch.StartNew();

        for (int i = 0; i < 10000000; i++)
        {
            res[i] = t.value * t.value;
        }

        watch.Stop();


        elapsedMs = watch.ElapsedMilliseconds;
        Debug.WriteLine("Multiply struct fields & Load into object array " + elapsedMs.ToString());


        watch = Stopwatch.StartNew();

        for (int i = 0; i < 10000000; i++)
        {
            res[i] = new TempStruct(t.value * t.value);
        }

        watch.Stop();


        elapsedMs = watch.ElapsedMilliseconds;
        Debug.WriteLine("Multiply struct fields & Load new struct into object array " + elapsedMs.ToString());



        watch = Stopwatch.StartNew();

        for (int i = 0; i < 10000000; i++)
        {
            res[i] = t * t;
        }

        watch.Stop();

        elapsedMs = watch.ElapsedMilliseconds;
        Debug.WriteLine("Multiply structs with overloaded operator a load struct into object array " + elapsedMs.ToString());

        watch = Stopwatch.StartNew();

        for (int i = 0; i < 10000000; i++)
        {
            res[i] = tclass.value * tclass.value;
        }

        watch.Stop();
        elapsedMs = watch.ElapsedMilliseconds;
        Debug.WriteLine("Multiply class fields & load into object array " + elapsedMs.ToString());

        watch = Stopwatch.StartNew();

        for (int i = 0; i < 10000000; i++)
        {
            res[i] = new TempClass(tclass.value * tclass.value);
        }

        watch.Stop();
        elapsedMs = watch.ElapsedMilliseconds;
        Debug.WriteLine("Multiply class fields & load new class into object array " + elapsedMs.ToString());

        watch = Stopwatch.StartNew();

        for (int i = 0; i < 10000000; i++)
        {
            res[i] = tclass * tclass;
        }

        watch.Stop();
        elapsedMs = watch.ElapsedMilliseconds;
        Debug.WriteLine("Multiply class using overloaded * operator & load class into object array " + elapsedMs.ToString());
    }
}    

Aucun commentaire:

Enregistrer un commentaire