В чем преимущество использования структур для таких единиц измерения, как температура?

Я запустил приведенный ниже код, чтобы проверить скорость некоторых распространенных применений в моей программе для единиц измерения, и был очень удивлен. С результатами: Все тесты были запущены 1 миллион раз в режиме отладки (режим запуска дал аналогичные различия). Кажется, что нет никакого реального преимущества в использовании структур для единиц измерения скорости с точки зрения скорости, поэтому может ли кто-нибудь сказать, какие преимущества могут быть? (У меня есть программа для обработки больших чисел, и это представляет для меня огромный интерес). Если приведенный ниже пример кода неверен, сообщите мне об этом. Что мне действительно нужно, так это наиболее удобный способ обработки единиц измерения, не делая код подробным (лучше всего было бы использовать UOM * UOM, а не UOM.Value * UOM.Value, но, по-видимому, это не самая эффективная скорость). Все время в мс.

Умножить на 7

Умножить поля структуры 8

Умножить свойство структуры 232

Умножение структуры температуры с использованием перегруженного оператора * 141

Умножение полей класса 7

Умножение и загрузка двойников в массив объектов 692

Умножение полей структуры и загрузка в массив объектов 719

Умножить поля структуры и загрузить новую структуру в массив объектов 926

Умножить структуры с перегруженным оператором на структуру загрузки в массив объектов 906

Умножение полей класса и загрузка в массив объектов 697

Умножить поля класса и загрузить новый класс в массив объектов 964

Умножить класс с помощью перегруженного оператора * и загрузить класс в массив объектов 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());
    }
}    

person user7168829    schedule 29.02.2020    source источник
comment
Преимущество скорости по сравнению с чем? Если это чистые переменные, почему вы вообще предполагаете, что будет преимущество в скорости? Struts не разгоняет процессор. Они намного быстрее в больших тестах по сравнению с классами, потому что они не производят мусора для сборщика мусора.   -  person TomTom    schedule 29.02.2020
comment
У меня сложилось впечатление, что структуры считаются лучше, чем классы для единиц измерения, но не вижу этого в приведенных ниже тестах. Классы удобны с наследованием. Хорошо, я понял проблему со сборщиком мусора, какой тест побольше? Я запускал его миллион раз.   -  person user7168829    schedule 29.02.2020
comment
Что-то, что перегружает память и принудительно собирает мусор.   -  person TomTom    schedule 29.02.2020
comment
Хорошо, мне интересно, смогу ли я жить с этим. У меня много итерационных расчетов на больших массивах, но классы не обязательно будут создаваться и уничтожаться на каждой итерации. Однако необходимость использовать UOM.Value вместо UOM только для ускорения меня раздражает.   -  person user7168829    schedule 29.02.2020


Ответы (1)


Разница между структурой и классом заключается в выделении памяти. Используя класс, у вас очень небольшие накладные расходы. Таким образом, вы не сможете заметить накладные расходы на производительность.

Тогда смысл использования структуры не в использовании ссылки. Следовательно, вам не нужно беспокоиться о том, что значение, измененное в 1 методе, может повлиять на другой метод.

person Alex - Tin Le    schedule 29.02.2020
comment
В любом случае я не вижу никаких накладных расходов на производительность, и я думаю, что модификатор «In» будет выполнять ту же работу, чтобы предотвратить изменение значений методом? - person user7168829; 29.02.2020
comment
Не знаете, что вы имели в виду под модификатором? - person Alex - Tin Le; 29.02.2020
comment
в параметре, предотвращает изменение любых значений методами, что-то вроде противоположности параметра Out, где вам нужно изменить значение - person user7168829; 29.02.2020
comment
Но если у вас есть сотни методов, вы не хотите дублировать их везде. И если у вас в команде десятки разработчиков, вы не уверены, что все это запомнят. - person Alex - Tin Le; 01.03.2020
comment
Я не хочу везде дублировать UOM.Value, чтобы ускорить его. Но похоже выбора нет. - person user7168829; 04.03.2020
comment
Вот так. Вы не хотите ускорить его на 1/100000 секунды и пожертвовать согласованностью кода и простотой обслуживания. Рад, что это проясняет ваш разум. - person Alex - Tin Le; 04.03.2020
comment
На самом деле ничего не очистил, важна скорость, а это миллионы вычислений. - person user7168829; 06.03.2020
comment
Что ж, я не проводил тест, но я думаю, что при вычислении 1 миллиона это стоило вам 1 секунды (время обработки ЦП) при использовании стойки. О каком именно расчете идет речь? 1000 миллиардов расчет? Если вы готовы потратить тысячи часов на кодирование/исправление/тестирование, чтобы сэкономить несколько тысяч секунд. Тогда я думаю, это твой выбор. - person Alex - Tin Le; 06.03.2020
comment
Кроме того, это зависит от вашей системы. Если вы строите систему торговли акциями, то да, 1 миллисекунда важна. Если вы строите прогноз погоды, данные отображаются с опозданием на несколько секунд, это не имеет большого значения. И никакие пользователи не поймут этого и не выиграют от этого. - person Alex - Tin Le; 06.03.2020
comment
Общее время обработки может составлять полчаса - person user7168829; 06.03.2020
comment
Это означает, что у вас есть около 2 миллиардов вычислений. Скажем, каждый раз, когда пользователь открывает браузер, вводит URL-адрес вашего веб-приложения, браузер отправляет запрос на сервер приложений. Сколько вычислений происходит за 1 запрос? - person Alex - Tin Le; 06.03.2020
comment
Это не то приложение. Эти ответы не имеют отношения к проблеме. - person user7168829; 06.03.2020
comment
Я знаю, извините, что отнял у вас время. - person Alex - Tin Le; 06.03.2020
comment
Нет проблем, я ценю вашу попытку помочь - person user7168829; 06.03.2020