Я занят чтением отличной книги Джона Скита C # In Depth. В разделе, посвященном упаковке и распаковке, он упоминает, что использование упакованных объектов связано с небольшими накладными расходами, которые, вероятно, могут повлиять на производительность в достаточно большом масштабе.

Поэтому я написал свои собственные тесты производительности, сложив вместе все числа от 1 до 100000000, используя цикл for. В одном случае я использовал Int32, затем int, затем я применял к object и возвращал обратно к int. Повторил все тесты 10 раз и взял среднее. Результаты (в секундах):

Int32 в среднем: 0,333

int avg: 0,326

средний объект: 1.061

Не большая разница между Int32 и int, но упаковка / распаковка заняла в 3 раза больше времени!

Так что, пожалуйста, помогите мне понять здесь: когда вы разыгрываете int на object, разве это не то же самое, что кастовать его на Int32? DotNetPerls утверждает, что int на самом деле просто псевдоним для Int32 - но если это так, то почему int постоянно работает быстрее, чем Int32, даже если это незначительно?

РЕДАКТИРОВАТЬ: По многочисленным просьбам, вот код теста:

const int SIZE = 100000000, ITERATIONS=10;
var intTimes = new List<double>();
var int32Times = new List<double>();
var objectTimes = new List<double>();

for (var n = 0; n < ITERATIONS; n++)
{
    Console.WriteLine("Iteration "+(n+1));
    Console.WriteLine("Testing using Int32");
    long result = 0;
    var sw = Stopwatch.StartNew();
    for (Int32 x = 0; x < SIZE; x++)
    {
        result += x;
    }
    sw.Stop();
    int32Times.Add(sw.Elapsed.TotalSeconds);
    Console.WriteLine("Result = {0} after {1:0.000} seconds", result, sw.Elapsed.TotalSeconds);

    Console.WriteLine("Testing using int");
    result = 0;
    sw = Stopwatch.StartNew();
    for (int x = 0; x < SIZE; x++)
    {
        result += x;
    }
    sw.Stop();
    Console.WriteLine("Result = {0} after {1:0.000} seconds", result, sw.Elapsed.TotalSeconds);
    intTimes.Add(sw.Elapsed.TotalSeconds);

    Console.WriteLine("Testing using object");
    result = 0;
    sw = Stopwatch.StartNew();
    for (int i = 0; i < SIZE; i++)
    {
        object o = i;
        result += (int) o;
    }
    sw.Stop();
    Console.WriteLine("Result = {0} after {1:0.000} seconds", result, sw.Elapsed.TotalSeconds);
    objectTimes.Add(sw.Elapsed.TotalSeconds);
}
Console.WriteLine("Summary:");
Console.WriteLine("Int32 avg: {0:0.000}", int32Times.Average());
Console.WriteLine("int avg: {0:0.000}", intTimes.Average());
Console.WriteLine("object avg: {0:0.000}", objectTimes.Average());
0
Shaul Behr 1 Май 2013 в 21:38
3
Нам нужно увидеть ваши тесты. Скорее всего, вы не разогреваете джиттер, и поэтому ваш первый будет работать медленнее, чем второй.
 – 
Kirk Woll
1 Май 2013 в 21:42
Тестовый код добавлен в вопрос.
 – 
Shaul Behr
1 Май 2013 в 22:00

1 ответ

Лучший ответ

Ключевое слово C # int является псевдонимом для System.Int32. Так что выполнять точно так же.

Конечно, во время измерения всегда есть колебания, потому что ваша машина выполняет и другие задачи.

Каждый раз, когда вы приводите int к object, небольшой фрагмент памяти (в куче) резервируется, и значение int копируется туда. Это требует некоторых усилий. Каждый раз, когда вы возвращаете его обратно, .NET сначала проверяет, действительно ли ваш объект содержит int (поскольку объект может содержать что угодно), а затем копирует значение обратно в int. Эта проверка также требует времени.

3
Martin Mulder 1 Май 2013 в 21:40
Я запускал тест несколько раз; каждый раз, когда цикл int был быстрее, чем цикл Int32, на 1-5%. Вы думаете, что это было просто совпадением?
 – 
Shaul Behr
1 Май 2013 в 21:43
1
Это одна программа, которую вы выполняете, выполняя все три теста, или вы модифицируете программу и запускаете один тест для одного типа данных?
 – 
Martin Mulder
1 Май 2013 в 21:44
1
Это должно быть совпадение (или ошибка в вашем тестовом коде). int и System.Int32 являются синонимами . Они будут производить идентичный код IL (что вы можете проверить с помощью Reflector).
 – 
Matthew Watson
1 Май 2013 в 21:52
2
Интересно. Я переключил int и Int32 в своем тестовом цикле, и теперь Int32 немного быстрее. Итак, вы правы, это не связано с различиями int и Int32, а скорее связано с какими-то накладными расходами при запуске этого цикла. @MatthewWatson - любезно предоставлено ping.
 – 
Shaul Behr
1 Май 2013 в 22:05
2
Вот почему спрашивают. При первом запуске фрагмента кода он впервые выполняет некоторые дополнительные операции, такие как загрузка сборок и т. Д. Это также вызовет некоторую задержку.
 – 
Martin Mulder
1 Май 2013 в 22:09