问题

以下哪一种表现最好?

我看到在JavaScript中实现的方法2具有巨大的性能提高,但是,我无法测量C#中的任何增益,并且想知道编译器是否已经执行了方法2,即使编写如方法1.

方法 2 背后的理论是代码在每次迭代时都不必访问 DataTable.Rows.Count,它可以简单地访问 int c。

方法1

 for (int i = 0; i < DataTable.Rows.Count; i++) {
    // Do Something
}
 

方法2

 for (int i = 0, c = DataTable.Rows.Count; i < c; i++) {
    // Do Something
}
 

  最佳答案

不,它不能这样做,因为没有办法随着时间的推移表达一个值的常数。

如果编译器应该能够做到这一点,那么代码必须保证返回值为常数的值,并且在循环的持续时间内不会发生变化。

但是,在这种情况下,您可以自由地将新行添加到数据表中作为循环的一部分,因此,按照您已经完成的方式,您应该做到这一点。

简而言之,如果 end-index 是变量以外的任何东西,编译器就不会这样做。

在变量的情况下,编译器只能查看loop-code并看到这个特定变量没有更改,它可能会这样做,并在启动循环之前将值加载到寄存器中,但是这样做的任何性能增益都很可能微不足道,除非循环体是空的.

结论:如果您知道或愿意接受,在循环的持续时间内,终端循环索引是常数,将其放入变量中。


编辑:重读您的帖子,是的,您也可能看到两种情况的性能增益微不足道,因为JITter优化了代码. JITter可能优化读取到包含行计数的数据表中的变量的直接访问中的内容索引,并且内存读取不是那么昂贵.另一方面,如果读取该属性是一个非常昂贵的操作,则会看到更明显的区别.

  相同标签的其他问题

c#performanceloops