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