【问题标题】:Performance implications of "too many" local variables in method?方法中“太多”局部变量的性能影响?
【发布时间】:2013-01-06 05:08:52
【问题描述】:

我被指派扩展软件的某个组件(由其他人编写)。它是为 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 并为字段/数组访问节省一些时间,但是 这么多 本地人的数量不是对性能有影响吗?例如,我听说过“注册压力”。

我只是不想在没有必要的情况下重写代码(即如果当前代码是好的),并且为了分析它,我需要重写它(否则只有一个版本 - 当前一,所以没有什么可比的......)。

如果不鼓励使用“太多”本地人,那么是否有一些不应超过的“最佳”最大值? (当然,我知道系统的堆栈大小是硬限制。)因为如果是这样,我可能还需要修改软件的其他部分(如果原作者好心将所有内容都放入本地)。

【问题讨论】:

  • 是否像在动画中那样为前置状态完成?
  • @pst:谢谢。我在其中发现了一个有趣的部分(请参阅 Stephen C 的答案下方的我的 cmets)。我对 Dalvik 和 VM 机制不太熟悉,所以不知道如何解释引用的部分。

标签: java android performance dalvik local-variables


【解决方案1】:

虽然大量局部变量可能会导致“寄存器压力”,但这仅仅意味着编译器可能会进行更多的内存提取。但是,另一种方法是(例如)用colour[0] 替换对r 的引用,这在理论上涉及索引检查和间接提取,可能导致更多的内存提取超出可用于注册的短缺。

总之,没有简单的答案。

所以,我倾向于不考虑代码,尤其是如果

  • 有证据表明原作者/以前的作者是通过剖析得出当前设计的,或者

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

【讨论】:

  • 我在三星 Galaxy S3 上没有遇到性能问题,但我也会在周一在其他手机上进行测试。顺便说一句,我在评论中引用了 Dalvik 链接:“因为在实践中,需要超过 16 个寄存器的方法并不常见,而且因为需要超过 8 个寄存器是相当普遍的,所以许多指令仅限于仅寻址第一个16 个寄存器。[..] 如果指令变体无法用于寻址所需寄存器,则预计寄存器内容会从原始寄存器移动到低寄存器(在操作之前)..."
  • "...和/或从低位结果寄存器移动到高位寄存器(在操作之后)。"这会以某种方式加重 JIT/性能吗?在 Galaxy S3 上,JIT 很强大,但是这个软件也必须在一些旧版本的平台上运行(周一测试)。
  • @ThomasCalc - “这会以某种方式加重 JIT/性能吗?”。它可以做到。但是您还需要考虑摆脱缓存的另一面;往上看。还要记住,硬件和/或 JIT 编译器的差异可能会挫败您手头优化的尝试。
  • “将在星期一测试” 我很好奇,这些测试显示了什么?
  • @aeracode - 他们可能表明那周没有星期一:-)
猜你喜欢
  • 1970-01-01
  • 2019-02-17
  • 1970-01-01
  • 2011-06-12
  • 2019-10-23
  • 1970-01-01
  • 2011-05-21
  • 2016-03-30
  • 1970-01-01
相关资源
最近更新 更多