局部变量或类字段?

我今天读了一篇关于 C#和Java 性能改进的文章 。

我仍然坚持这个:


19.不要过度使用实例变量

使用局部变量可以提高性能。 示例1中的代码执行速度比示例2中的代码快。

例1:

public void loop() { int j = 0; for ( int i = 0; i<250000;i++){ j = j + 1; } } 

例2:

 int i; public void loop() { int j = 0; for (i = 0; i<250000;i++){ j = j + 1; } } 

实际上,我不明白为什么在我可以对字段进行简单访问时,每次调用loop函数时实例化一些内存并释放它应该更快。

这是纯粹的好奇心,我不是试图将变量’i’放在类的范围内:p是否真的使用局部变量更快? 或者只是在某些情况下?

  1. 比堆更快堆栈。

     void f() { int x = 123; // <- located in stack } int x; // <- located in heap void f() { x = 123 } 
  2. 不要忘记地方数据的原则 。 应该在CPU缓存中更好地缓存本地数据。 如果数据接近,它们将完全加载到CPU缓存中,并且CPU不必从内存中获取它们。

性能低至获取变量所需的步骤数。 本地变量地址在编译时是已知的(它们是堆栈上的已知偏移量),用于访问加载对象“this”的成员以获取实际对象的地址,然后才能获取成员变量的地址。

即使它会,但在这种情况下几乎没有可衡量的差异。 在第一种情况下,可以在处理器注册表级别上进行一些优化,但同样:

  • 这几乎无关紧要
  • 更重要的是,往往是不可预测的。

在记忆方面,它完全相同 ,没有任何区别。

第一种情况它通常更好:当你声明变量时,它是立即使用的,这是常用的良好模式,因为它是

  • 易于理解(职责范围)
  • 简单的重构

我怀疑差异很小,但是在变量是对象成员的情况下,每次访问都需要通过this (有效)进行间接,而局部变量则不需要。

更一般地说,该对象不需要成员i ,它仅在循环的上下文中使用,因此在任何情况下使其在本地使用都更好。

我测试了500,000次迭代的计算,其中我在本地使用了大约20个变量,并且使用了字段。 局部变量测试大约是20毫秒,带有字段的测试大约是30毫秒。 使用局部变量时,性能显着提高。

性能差异是否相关,取决于项目。 在您的平均业务应用程序中,性能增益可能不明显,最好是可读/可维护代码,但我正在研究声音合成软件,其中像这样的纳米优化实际上变得相关。

在C#中,另一个细微差别是生成的MSIL指令的数量(我猜它在Java中类似)。

加载实例字段需要两条指令:

 ldarg.0 // load "this" reference onto stack ldfld MyClass.myField // find the field and load its value 

…但只需要一条指令来加载局部变量:

 ldloc.0 // load the value at index 0 from the list of local variables