.NET Integer vs Int16?
У меня сомнительная практика кодирования.
Когда мне нужно выполнить итерацию по небольшому списку элементов, чей лимит под знаком 32000
, я использую Int16
для моего i-го типа переменной вместо Integer
. Я делаю это, потому что я предполагаю, что использование Int16
более эффективно, чем полномасштабное Integer
.
Неужели я ошибаюсь? Нет ли эффективной разницы в производительности между использованием Int16
vs a Integer
? Должен ли я перестать использовать Int16
и просто придерживаться Integer
для всех моих потребностей в подсчете/итерации?
Ответы
Ответ 1
В соответствии с приведенной ниже ссылкой среда выполнения оптимизирует производительность Int32 и рекомендует их для счетчиков и других часто выполняемых операций.
Из книги: Учебный комплект MCTS для самостоятельного обучения (экзамен 70-536): Microsoft®.NET Framework 2.0-Foundation Development Foundation
Глава 1: "Основы фундамента"
Урок 1: "Использование типов значений"
Лучшие практики: оптимизация производительности со встроенными типами
Рабочая среда оптимизирует производительность 32-разрядных целых типов (Int32 и UInt32), поэтому используйте эти типы для счетчиков и других часто доступных интегральных переменных.
Для операций с плавающей запятой Double является наиболее эффективным типом, поскольку эти операции оптимизируются с помощью аппаратного обеспечения.
Кроме того, в таблице 1-1 в том же разделе перечислены рекомендуемые применения для каждого типа.
Релевантно:
- Int16 - Взаимодействие и другие специализированные применения
- Int32 - целые числа и счетчики
- Int64 - большие целые числа
Ответ 2
Вы должны почти всегда использовать Int32
или Int64
(и, нет, вы не получаете кредит с помощью UInt32
или UInt64
) при переходе по массиву или коллекции по индекс.
Наиболее очевидной причиной менее эффективной является то, что все индексы массива и коллекции, найденные в BCL, принимают Int32
s, поэтому неявный листинг всегда будет происходить в коде, который пытается использовать Int16
в качестве индекса.
Менее очевидная причина (и причина, по которой массивы принимают Int32
как индекс), заключается в том, что спецификация CIL говорит, что все значения стека операций либо Int32
, либо Int64
, Каждый раз, когда вы загружаете или сохраняете значение для любого другого целочисленного типа (Byte
, SByte
, UInt16
, Int16
, UInt32
или UInt64
), применяется операция неявного преобразования. Неподписанные типы не имеют штрафа за загрузку, но для хранения значения это означает усечение и возможную проверку переполнения. Для подписанных типов каждый знак нагрузки расширяет, а каждый знак хранилища сбрасывается (и имеет возможную проверку переполнения).
Место, которое вам больше всего повредит, - это сам цикл, а не доступ к массиву. Например, возьмите этот невинный вид:
for (short i = 0; i < 32000; i++) {
...
}
Выглядит хорошо, не так ли? Неа! Вы можете в принципе игнорировать инициализацию (short i = 0
), так как это происходит только один раз, но сравнение (i<32000
) и приращение (i++
) частей происходит 32000 раз. Здесь несколько pesudo-code для того, что эта вещь выглядит на уровне машины:
Int16 i = 0;
LOOP:
Int32 temp0 = Convert_I16_To_I32(i); // !!!
if (temp0 >= 32000) goto END;
...
Int32 temp1 = Convert_I16_To_I32(i); // !!!
Int32 temp2 = temp1 + 1;
i = Convert_I32_To_I16(temp2); // !!!
goto LOOP;
END:
В нем есть 3 преобразования, которые запускаются 32000. И их можно было бы полностью избежать, просто используя Int32
или Int64
.
Обновление: Как я уже сказал в комментарии, сейчас я написал сообщение в блоге по этой теме .NET Integral Data Types And You
Ответ 3
Int16 может фактически быть менее эффективным, поскольку инструкции x86 для доступа к словарю занимают больше места, чем инструкции для доступа к dword. Это будет зависеть от того, что делает JIT. Но независимо от того, что это почти наверняка не является более эффективным при использовании в качестве переменной в итерации.
Ответ 4
Противоположно.
32 (или 64) битовых целых числа быстрее, чем int16. В общем, собственный тип данных является самым быстрым.
Int16 хороши, если вы хотите сделать свои структуры данных максимально возможными. Это экономит место и может повысить производительность.
Ответ 5
Любая разница в производительности будет настолько крошечной на современном оборудовании, что для всех целей и задач это не будет иметь никакого значения. Попробуйте написать пару тестовых жгутов и запустить их в несколько сотен раз, принять среднее время завершения цикла, и вы увидите, что я имею в виду.
Это может иметь смысл с точки зрения хранилища, если у вас очень ограниченные ресурсы - встроенные системы с небольшим стеком, проводные протоколы, предназначенные для медленных сетей (например, GPRS и т.д.) и т.д.
Ответ 6
Никогда не предполагайте эффективность.
То, что является или не является более эффективным, будет варьироваться от компилятора к компилятору и от платформы к платформе. Если вы на самом деле не протестировали это, невозможно определить, эффективнее ли int16 или int.
Я бы просто придерживался ints, если вы не столкнулись с проверенной проблемой производительности, которая использует исправления int16.
Ответ 7
Используйте Int32 на 32-разрядных машинах (или Int64 на 64-разрядных машинах) для достижения максимальной производительности. Используйте меньший целочисленный тип, если вы действительно обеспокоены тем пространством, которое он занимает (может быть, медленнее, хотя).
Ответ 8
Другие здесь правильны, используйте только значение Int32 (для 32-разрядного кода)/Int64 (для 64-разрядного кода), если это необходимо для экстремальных требований к хранению или для другого уровня принудительного применения в поле бизнес-объекта (в этом случае, конечно, вы должны иметь правильную проверку уровня).
И вообще, не беспокойтесь об эффективности, пока не возникнет проблема с производительностью. И в этом случае профилируйте его. И если угадать и проверять оба пути во время профилирования не поможет вам, проверьте код IL.
Хороший вопрос. Вы узнаете больше о том, как это делает компилятор. Если вы хотите научиться более эффективно программировать, изучение основ ИЛ и того, как компиляторы С#/VB выполняют свою работу, будет отличной идеей.
Ответ 9
Я не могу себе представить, что у Int16 vs. int есть значительное увеличение производительности.
Вы сохраняете некоторые биты в объявлении переменной.
И определенно не стоит хлопот, когда спецификации меняются, и все, что вы рассчитываете, может теперь переместиться выше 32767, и вы обнаружите, что когда ваше приложение начинает бросать исключения...
Ответ 10
Нет существенного прироста производительности при использовании типа данных, меньшего, чем Int32, на самом деле, я читал где-то, что использование Int32 будет быстрее Int16 из-за выделения памяти