我有一个可疑的编码实践。
当我需要遍历计数限制低于的项目的小列表时,我32000
使用i变量类型而不是. 我这样做是因为我认为使用.Int16
Integer
Int16
Integer
我错了吗?Int16
使用 an和 an之间没有有效的性能差异Integer
吗?我应该停止使用Int16
并坚持Integer
我所有的计数/迭代需求吗?
在按索引循环遍历数组或集合时,您几乎应该总是使用Int32
or (并且,不,使用orInt64
不会获得信任)。UInt32
UInt64
它效率较低的最明显原因是在 BCL 中找到的所有数组和集合索引都使用s,因此在尝试使用s 作为索引的代码中总是Int32
会发生隐式转换。Int16
不太明显的原因(以及数组Int32
作为索引的原因)是 CIL 规范规定所有操作堆栈值都是 Int32
or Int64
。每次将值加载或存储到任何其他整数类型(Byte
、SByte
、UInt16
、Int16
、UInt32
或UInt64
)时,都会涉及到隐式转换操作。无符号类型对加载没有惩罚,但对于存储值,这相当于截断和可能的溢出检查。对于有符号类型,每个加载符号扩展,每个存储符号折叠(并且可能进行溢出检查)。
这对你伤害最大的地方是循环本身,而不是数组访问。例如,采取这个看似无辜的循环:
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
根据以下参考,运行时优化了Int32的性能,并推荐它们用于计数器和其他频繁访问的操作。
出自本书:MCTS 自定进度培训套件(考试 70-536):Microsoft® .NET Framework 2.0 — 应用程序开发基础
第 1 章:“框架基础”
第 1 课:“使用值类型”
最佳实践:使用内置类型优化性能
运行时优化了 32 位整数类型(Int32 和 UInt32)的性能,因此将这些类型用于计数器和其他经常访问的整数变量。
对于浮点运算,Double 是最有效的类型,因为这些运算是由硬件优化的。
此外,同一节中的表 1-1 列出了每种类型的推荐用途。与此讨论相关:
Int16 实际上可能效率较低,因为用于字访问的 x86 指令比用于 dword 访问的指令占用更多空间。这将取决于 JIT 的作用。但无论如何,在迭代中用作变量时几乎肯定不会更有效。
反之亦然。
32(或 64)位整数比 int16 更快。通常,本机数据类型是最快的一种。
如果你想让你的数据结构尽可能精简,Int16 就很好。这可以节省空间并可以提高性能。
在现代硬件上,任何性能差异都将是如此微小,以至于无论出于何种目的和目的,它都不会产生任何影响。尝试编写几个测试工具并运行它们几百次,取平均循环完成时间,你就会明白我的意思了。
如果您的资源非常有限——嵌入式系统的堆栈很小,专为慢速网络(例如 GPRS 等)设计的有线协议等,从存储的角度来看,这可能是有意义的。
永远不要假设效率。
什么是更有效或不是更有效将因编译器和平台而异。除非您实际对此进行了测试,否则无法判断是 int16 还是 int 更有效。
除非您遇到使用 int16 修复的经过验证的性能问题,否则我会坚持使用 int。
在 32 位机器上使用 Int32(或在 64 位机器上使用 Int64)以获得最快的性能。如果您真的关心它占用的空间,请使用较小的整数类型(尽管可能会更慢)。
这里的其他都是正确的,如果你需要它来满足极端的存储要求,或者为了对业务对象字段进行其他级别的强制(你应该当然,在这种情况下仍然有适当的级别验证)。
通常,在出现性能问题之前不要担心效率。在这种情况下,分析它。如果在分析时猜测和检查两种方式对您的帮助不够,请检查 IL 代码。
不过是个好问题。您正在了解更多关于编译器如何完成它的事情。如果您想学习更有效地编程,学习 IL 的基础知识以及 C#/VB 编译器如何工作将是一个好主意。
我无法想象 Int16 与 int 相比有任何显着的性能提升。
您在变量声明中保存了一些位。
当规格发生变化时,绝对不值得麻烦,无论您计算什么现在都可以超过 32767,并且您发现当您的应用程序开始抛出异常时......
使用小于 Int32 的数据类型没有显着的性能提升,事实上,我在某处读到,由于内存分配,使用 Int32 会比 Int16 更快