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





Верно и обратное.
32 (или 64) битные целые числа быстрее, чем int16. В общем, родной тип данных самый быстрый.
Int16 хорош, если вы хотите сделать свои структуры данных как можно более компактными. Это экономит место и может повысить производительность.
На самом деле Int16 может быть эффективным меньше, потому что инструкции x86 для доступа к словам занимают больше места, чем инструкции для доступа к двойным словам. Это будет зависеть от того, что делает JIT. Но несмотря ни на что, он почти наверняка не эффективен при использовании более в качестве переменной в итерации.
Никогда не предполагайте эффективности.
Что является более эффективным, а что нет, будет варьироваться от компилятора к компилятору и от платформы к платформе. Если вы на самом деле не проверили это, невозможно определить, является ли int16 или int более эффективным.
Я бы просто придерживался ints, если вы не столкнетесь с доказанной проблемой производительности, связанной с исправлениями int16.
Я не могу представить себе существенного прироста производительности Int16 по сравнению с int.
Вы сохраняете некоторые биты в объявлении переменной.
И определенно не стоит беспокоиться, когда спецификации меняются и что бы вы ни считали, может сейчас превышает 32767, и вы обнаруживаете, что когда ваше приложение начинает генерировать исключения ...
Любая разница в производительности на современном оборудовании будет настолько крошечной, что для всех целей и задач она не будет иметь никакого значения. Попробуйте написать пару тестовых программ и запустите их обе несколько сотен раз, возьмите среднее время завершения цикла, и вы поймете, что я имею в виду.
Это может иметь смысл с точки зрения хранилища, если у вас очень ограниченные ресурсы - встроенные системы с крошечным стеком, проводные протоколы, предназначенные для медленных сетей (например, GPRS и т. д.), И так далее.
Используйте Int32 на 32-битных машинах (или Int64 на 64-битных машинах) для максимальной производительности. Используйте меньший целочисленный тип, если В самом деле беспокоит занимаемое пространство (хотя может быть медленнее).
Нет значительного увеличения производительности при использовании типа данных меньшего, чем Int32, на самом деле, я где-то читал, что использование Int32 будет быстрее, чем Int16 из-за выделения памяти
Вы должны почти всегда использовать Int32 или Int64 (и, нет, вы не получаете кредит, используя UInt32 или UInt64) при циклическом обходе массива или коллекции по индексу.
Наиболее очевидная причина того, что он менее эффективен, заключается в том, что все индексы массивов и коллекций, найденные в BCL, принимают Int32, поэтому неявное приведение всегда произойдет в коде, который пытается использовать Int16 в качестве индекса.
Менее очевидная причина (и причина, по которой массивы принимают Int32 в качестве индекса) заключается в том, что в спецификации CIL указано, что все значения стека операций - это либоInt32 или Int64. Каждый раз, когда вы загружаете или сохраняете значение в любой другой целочисленный тип (Byte, SByte, UInt16, Int16, UInt32 или UInt64), выполняется операция неявного преобразования. Беззнаковые типы не имеют штрафа за загрузку, но для сохранения значения это равносильно усечению и возможной проверке переполнения. Для подписанных типов каждый load sign-extends, и каждый store sign-collaps (и имеет возможную проверку переполнения).
Больше всего от этого вы столкнетесь в самом цикле, а не в доступе к массиву. Например, возьмите этот невинно выглядящий цикл:
for (short i = 0; i < 32000; i++) {
...
}
Выглядит хорошо, правда? Неа! Вы можете в основном игнорировать инициализацию (short i = 0), поскольку она происходит только один раз, но части сравнения (i<32000) и увеличения (i++) происходят 32000 раз. Вот небольшой псевдокод того, как эта штука выглядит на машинном уровне:
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 и вы
Спасибо, Ядын. Я добавил это в свою очередь для того, о чем мне следует писать, когда я действительно начинаю блог. В прошлом я много раз видел, как люди совершали эту ошибку.
Согласно приведенной ниже ссылке, время выполнения оптимизирует производительность Int32 и рекомендует их для счетчиков и других часто используемых операций.
Из книги: Комплект для самостоятельного обучения MCTS (экзамен 70-536): Microsoft® .NET Framework 2.0 - Application Development Foundation
Глава 1: «Основы Framework»
Урок 1: «Использование типов значений»
Best Practices: Optimizing performance with built-in types
The runtime optimizes the performance of 32-bit integer types (Int32 and UInt32), so use those types for counters and other frequently accessed integral variables.
For floating-point operations, Double is the most efficient type because those operations are optimized by hardware.
Кроме того, в Таблице 1-1 того же раздела перечислены рекомендуемые применения для каждого типа. Имеет отношение к этому обсуждению:
Остальные здесь верны, используйте только меньше, чем Int32 (для 32-битного кода) / Int64 (для 64-битного кода), если он вам нужен для экстремальных требований к хранилищу или для другого уровня применения в поле бизнес-объекта (вы все равно должны иметь в этом случае, конечно, проверку на надлежащий уровень).
И вообще, не беспокойтесь об эффективности, пока не возникнет проблема с производительностью. И в этом случае профилируйте его. И если угадывание и проверка обоими способами при профилировании вам недостаточно, проверьте код IL.
Но хороший вопрос. Вы узнаете больше о том, как это делает компилятор. Если вы хотите научиться программировать более эффективно, изучение основ IL и того, как компиляторы C# / VB выполняют свою работу, было бы отличной идеей.
Он просит .net, поэтому платформа очень хорошо определена.