52

我有一个可疑的编码实践。

当我需要遍历计数限制低于的项目的小列表时,我32000使用i变量类型而不是. 我这样做是因为我认为使用.Int16IntegerInt16Integer

我错了吗?Int16使用 an和 an之间没有有效的性能差异Integer吗?我应该停止使用Int16并坚持Integer我所有的计数/迭代需求吗?

4

10 回答 10

88

在按索引循环遍历数组或集合时,您几乎应该总是使用Int32or (并且,不,使用orInt64不会获得信任)。UInt32UInt64

它效率较低的最明显原因是在 BCL 中找到的所有数组和集合索引都使用s,因此在尝试使用s 作为索引的代码中总是Int32会发生隐式转换。Int16

不太明显的原因(以及数组Int32作为索引的原因)是 CIL 规范规定所有操作堆栈值都是 Int32or Int64。每次将值加载或存储到任何其他整数类型(ByteSByteUInt16Int16UInt32UInt64)时,都会涉及到隐式转换操作。无符号类型对加载没有惩罚,但对于存储值,这相当于截断和可能的溢出检查。对于有符号类型,每个加载符号扩展,每个存储符号折叠(并且可能进行溢出检查)。

这对你伤害最大的地方是循环本身,而不是数组访问。例如,采取这个看似无辜的循环:

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只需使用or就可以完全避免它们Int64

更新:正如我在评论中所说,我现在实际上已经写了一篇关于这个主题的博客文章,.NET Integral Data Types And You

于 2008-09-24T20:38:03.307 回答
54

根据以下参考,运行时优化了Int32的性能,并推荐它们用于计数器和其他频繁访问的操作。

出自本书:MCTS 自定进度培训套件(考试 70-536):Microsoft® .NE​​T Framework 2.0 — 应用程序开发基础

第 1 章:“框架基础”
第 1 课:“使用值类型”

最佳实践:使用内置类型优化性能

运行时优化了 32 位整数类型(Int32 和 UInt32)的性能,因此将这些类型用于计数器和其他经常访问的整数变量。

对于浮点运算,Double 是最有效的类型,因为这些运算是由硬件优化的。

此外,同一节中的表 1-1 列出了每种类型的推荐用途。与此讨论相关:

  • Int16 - 互操作和其他专门用途
  • Int32 - 整数和计数器
  • Int64 - 大整数
于 2008-09-25T03:36:40.383 回答
11

Int16 实际上可能效率较低,因为用于字访问的 x86 指令比用于 dword 访问的指令占用更多空间。这将取决于 JIT 的作用。但无论如何,在迭代中用作变量时几乎肯定不会更有效。

于 2008-09-24T18:47:54.727 回答
9

反之亦然。

32(或 64)位整数比 int16 更快。通常,本机数据类型是最快的一种。

如果你想让你的数据结构尽可能精简,Int16 就很好。这可以节省空间并可以提高性能。

于 2008-09-24T18:46:54.527 回答
3

在现代硬件上,任何性能差异都将是如此微小,以至于无论出于何种目的和目的,它都不会产生任何影响。尝试编写几个测试工具并运行它们几百次,取平均循环完成时间,你就会明白我的意思了。

如果您的资源非常有限——嵌入式系统的堆栈很小,专为慢速网络(例如 GPRS 等)设计的有线协议等,从存储的角度来看,这可能是有意义的。

于 2008-09-24T18:49:50.837 回答
2

永远不要假设效率。

什么是更有效或不是更有效将因编译器和平台而异。除非您实际对此进行了测试,否则无法判断是 int16 还是 int 更有效。

除非您遇到使用 int16 修复的经过验证的性能问题,否则我会坚持使用 int。

于 2008-09-24T18:47:57.237 回答
2

在 32 位机器上使用 Int32(或在 64 位机器上使用 Int64)以获得最快的性能。如果您真的关心它占用的空间,请使用较小的整数类型(尽管可能会更慢)。

于 2008-09-24T18:51:17.837 回答
1

这里的其他都是正确的,如果你需要它来满足极端的存储要求,或者为了对业务对象字段进行其他级别强制(你应该当然,在这种情况下仍然有适当的级别验证)。

通常,在出现性能问题之前不要担心效率。在这种情况下,分析它。如果在分析时猜测和检查两种方式对您的帮助不够,请检查 IL 代码。

不过是个好问题。您正在了解更多关于编译器如何完成它的事情。如果您想学习更有效地编程,学习 IL 的基础知识以及 C#/VB 编译器如何工作将是一个好主意。

于 2008-09-26T03:37:56.627 回答
0

我无法想象 Int16 与 int 相比有任何显着的性能提升。

您在变量声明中保存了一些位。

当规格发生变化时,绝对不值得麻烦,无论您计算什么现在都可以超过 32767,并且您发现当您的应用程序开始抛出异常时......

于 2008-09-24T18:48:02.760 回答
0

使用小于 Int32 的数据类型没有显着的性能提升,事实上,我在某处读到,由于内存分配,使用 Int32 会比 Int16 更快

于 2008-09-24T18:53:46.130 回答