方法中有“太多”本地变量会对性能产生什么影响?

5

我被指派扩展一个软件的某个组件(由他人编写)。它是为Android编写的,完全使用Java编写(据我所知没有本地/ C ++组件)。

在熟悉代码时,我遇到了一个方法(用于渲染类的绘图方法)。该方法涉及一个更新对象的大循环(然后另一个方法稍后将呈现它们)。该方法的创建者似乎将所有/大多数成员变量和数组以及其他对象的字段缓存到本地变量中,循环之前。代码看起来像这样:

    float[] coordArr = mCoordArr;
    float[] texCoordArr = mTexCoordArr;
    float[] cArray = mColArray;

    // ... there are further locals too, I didn't copy all here

    float[] color = mColor;
    float r = color[0];
    float g = color[1];
    float b = color[2];
    float a = color[3];

    int texw = mTexW;
    int texH = mTexH;
    Font font = mFont;
    float[] ccords = font.ccords;
    float cf = font.cf;
    float cu = font.cu;
    int len = mCurLength;

    // Update the objects
    for (int i = 0; i < len; ++i) {

        // A quite big loop body

        // ... all locals are accessed from the loop

    }

渲染组件是单线程的,其所有成员变量也是如此。我使用Java/Dalvik反汇编器进行了检查,字节码注释显示该方法使用了41个寄存器。我认为作者将它们缓存到本地变量中以帮助JIT并节省一些时间用于字段/数组访问,但这么多本地变量是否会影响性能?例如,我听说过“寄存器压力”的问题。
如果当前代码没有问题,我就不想重写它(即使没有必要)。为了对其进行分析,我需要重写它(否则只有一个版本——当前版本,因此无法与其他版本进行比较...)。
如果使用“太多”本地变量是不被鼓励的,那么是否有一种“最佳”最大值不应超过?(当然,我知道系统堆栈大小是硬限制。)因为如果是这种情况,我可能还需要修改软件的其他部分(如果原始作者足够善良将所有内容放入本地变量中)。

像动画中的预后状态一样完成了吗? - ChiefTwoPencils
1
一些注释:http://source.android.com/tech/dalvik/dalvik-bytecode.html - user166390
1
@pst:谢谢。我在里面发现了一个有趣的部分(请看下面Stephen C的回答中我的评论)。我对Dalvik和VM机制不是很有经验,所以不确定如何解释引用的部分。 - Thomas Calc
1个回答

6

当局部变量过多时,可能会导致"寄存器压力",这意味着编译器可能会执行更多的内存获取操作。然而,另一种选择是(例如)用colour[0]替换对r的引用,理论上涉及一个索引检查和一个间接获取,这可能导致更多的内存获取操作,而不能归因于寄存器短缺。

简而言之,没有简单的答案。

因此,如果:

  • 有证据表明原始/先前的作者根据分析得出了当前的设计,或者

  • 代码已经运行得足够快...

我倾向于不改动代码。


我在三星Galaxy S3上没有遇到性能问题,但我打算在周一也在其他手机上进行测试。顺便引用我在评论中收到的Dalvik链接:“实际上,一个方法需要超过16个寄存器的情况并不常见,而需要超过8个寄存器的情况相当普遍,因此许多指令只能访问前16个寄存器。[...] 在无法使用某个指令变体来访问所需寄存器的情况下,预期将寄存器内容从原始寄存器移动到低位寄存器(在操作之前)...” - Thomas Calc
“...并/或者从低结果寄存器移动到高寄存器(操作后)。这会对JIT/性能造成负担吗?在Galaxy S3上,JIT非常强大,但是这个软件也必须在一些旧版本的平台上运行(将在周一进行测试)。” - Thomas Calc
1
@ThomasCalc - "这会不会对JIT/性能产生负面影响?" 可能会有。但你还需要考虑消除缓存的另一面;请参见以上内容。同时要记住,硬件或JIT编译器的差异可能会打败您手动优化的尝试。 - Stephen C
“将在星期一进行测试” 我很好奇,这些测试显示了什么? - aeracode
@aeracode - 他们可能展示了那周没有星期一 :-) - Stephen C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接