.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 из-за выделения памяти