14

我今天阅读了一篇关于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 使用局部变量是否更快?或者也许只是在某些情况下?

4

6 回答 6

13
  1. 堆栈比堆快。

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

于 2013-07-17T15:20:24.680 回答
7

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

于 2013-07-17T15:15:56.687 回答
3

在 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
于 2018-01-13T14:49:51.310 回答
2

即使是这样,在这种情况下也会有几乎无法测量的差异。可能在第一种情况下,处理器注册表级别进行了一些优化,但同样:

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

在内存方面,完全一样,没有任何区别。

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

  • 易于理解(职责范围)
  • 轻松重构
于 2013-07-17T15:18:27.507 回答
2

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

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

于 2016-11-03T00:24:52.000 回答
1

我怀疑几乎没有区别,但是在变量是对象成员的情况下,每次访问都需要this(有效地)间接,而局部变量则不需要。

更一般地说,对象不需要成员i,它只在循环的上下文中使用,因此在任何情况下将其设置为本地使用会更好。

于 2013-07-17T15:14:07.820 回答