.NET Integer vs Int16?

У меня сомнительная практика кодирования.

Когда мне нужно выполнить итерацию через небольшой список элементов, чей лимит счета меньше 32000 , я использую Int16 для моего типа переменной i вместо Integer . Я делаю это, потому что я предполагаю, что использование Int16 более эффективно, чем полноразмерный Integer .

Я ошибаюсь? Нет ли эффективной разницы в производительности между использованием Int16 и Integer ? Должен ли я прекратить использование Int16 и просто придерживаться Integer для всех моих потребностей в подсчете / итерации?

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

Из книги: Учебный комплект MCTS для самостоятельного обучения (экзамен 70-536): Microsoft® .NET Framework 2.0-Application Development Foundation

Глава 1: «Основы основы»
Урок 1: «Использование типов значений»

Рекомендации: оптимизация производительности со встроенными типами

Время выполнения оптимизирует производительность 32-разрядных целых типов (Int32 и UInt32), поэтому используйте эти типы для счетчиков и других часто доступных интегральных переменных.

Для операций с плавающей запятой Double является наиболее эффективным типом, поскольку эти операции оптимизируются с помощью аппаратного обеспечения.

Кроме того, в таблице 1-1 в том же разделе перечислены рекомендуемые применения для каждого типа. Относительно этого обсуждения:

  • Int16 – Взаимодействие и другие специализированные виды использования
  • Int32 – Целые числа и счетчики
  • Int64 – большие целые числа

Вы должны почти всегда использовать Int32 или Int64 (и, нет, вы не получаете кредит с помощью UInt32 или UInt32 ) при переходе по массиву или коллекции по индексу.

Наиболее очевидной причиной того, что он менее эффективен, является то, что все индексы массива и коллекции, найденные в BCL, принимают Int32 s, поэтому неявный приведение всегда происходит в коде, который пытается использовать Int16 s в качестве индекса.

Менее очевидная причина (и причина, по которой массивы принимают Int32 в качестве индекса) заключается в том, что спецификация CIL говорит, что все значения стека операций являются Int32 или Int64 . Каждый раз, когда вы загружаете или сохраняете значение для любого другого целочисленного типа ( UInt16 , 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

Int16 может фактически быть менее эффективным, поскольку инструкции x86 для доступа к словарю занимают больше места, чем инструкции для доступа к dword. Это будет зависеть от того, что делает JIT. Но независимо от того, что почти наверняка не является более эффективным при использовании в качестве переменной в итерации.

И наоборот.

32 (или 64) битовых целых числа быстрее, чем int16. В общем, собственный тип данных является самым быстрым.

Int16 хороши, если вы хотите сделать ваши структуры данных максимально возможными. Это экономит место и может повысить производительность.

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

Это может иметь смысл с точки зрения хранения, если у вас очень ограниченные ресурсы – встроенные системы с небольшим стеком, проводные протоколы, предназначенные для медленных сетей (например, GPRS и т. Д.) И т. Д.

Никогда не считайте эффективность.

То, что является или не является более эффективным, будет варьироваться от компилятора к компилятору и от платформы к платформе. Если вы на самом деле не протестировали это, невозможно определить, эффективнее ли int16 или int.

Я бы просто придерживался ints, если вы не столкнулись с проверенной проблемой производительности, которая использует исправления int16.

Для достижения максимальной производительности используйте Int32 на 32-разрядных машинах (или Int64 на 64-разрядных машинах). Используйте меньший целочисленный тип, если вы действительно обеспокоены пространством, которое он занимает (может быть, медленнее, хотя).

Остальные здесь правильные, используйте только для Int32 (для 32-битного кода) / Int64 (для 64-разрядного кода), если вам это нужно для экстремальных требований к хранению или для другого уровня принудительного применения в поле бизнес-объекта (вы должны в этом случае, конечно, по-прежнему есть правильная проверка уровня).

И вообще, не беспокойтесь об эффективности, пока не возникнет проблема с производительностью. И в этом случае профилируйте его. И если угадай и проверив обоими способами, пока профилирование не поможет вам, проверьте код IL.

Хороший вопрос. Вы узнаете больше о том, как это делает компилятор. Если вы хотите научиться более эффективно программировать, изучение основ ИЛ и как компиляторы C # / VB выполняют свою работу, это отличная идея.

Я не могу себе представить, что есть значительный прирост производительности на Int16 против int.

Вы сохраняете некоторые биты в объявлении переменной.

И определенно не стоит хлопот, когда спецификации меняются, и все, что вы рассчитываете, может переместиться выше 32767, и вы обнаружите, что когда ваше приложение начинает бросать исключения …

Нет существенного прироста производительности при использовании типа данных, меньшего, чем Int32, на самом деле, я где-то читал, что использование Int32 будет быстрее Int16 из-за выделения памяти

  • JAXB: Как изменить имена classов, сгенерированных XJC, когда тип attr указан в XSD?
  • Когда использовать значения без знака над подписанными?
  • Почему Java API использует int вместо короткого или байтового?
  • Рекомендации по хранению почтовых адресов в базе данных (РСУБД)?
  • Какой тип данных использовать для hashированного поля пароля и какой длины?
  • Строка к двоичной в C #
  • Взаимодействие Java Raw Type и generics
  • Почему эти уравнения деления приводят к нулю?
  • Как написать функцию для общих чисел?
  • Типы данных PostgreSQL и C #
  • Вычисление переменной с использованием переменной типа
  • Давайте будем гением компьютера.