【问题标题】:A Java bounds-checking optimization exampleJava 边界检查优化示例
【发布时间】:2014-02-12 01:49:19
【问题描述】:

我读过一些 JVM 可以通过删除边界检查来优化代码执行。我想弄清楚的是哪种编码技术会更好。

在下面的方法 example1 中,JVM 是否会弄清楚并消除对 source[index] 引用的边界检查?

example2 是更好的代码实践吗?看起来是这样,但在循环内的某些算法中,索引超出范围是正常情况。所以你不想在那个循环中生成大量的异常对象。

public void example1(int [] source, int index) {
    if (index >= 0 && index < source.length)
        System.out.println("Value is " + source[index]);
    else 
        System.out.println("Out of range: " + index);
}

public void example2(int [] source, int index) {
    try {        
        System.out.println("Value is " + source[index]);        
    } catch (IndexOutOfBoundsException exp) {
        System.out.println("Out of range: " + index);
    }
}

这些代码片段仅具有代表性。我知道在这些示例中,边界检查对性能几乎没有影响。但是,我正在开发一个嵌入式协议应用程序,其中冗余边界检查将加起来。

【问题讨论】:

  • This 这里一些同事的论文对你来说应该很有趣。我认为这些更改已包含在热点中,但不确定。无论如何,从性能和编码实践的角度来看,第二个示例肯定更差。
  • @AlanObject,边界检查是多个数量级,比对输出的调用要小。在大多数情况下,这没有任何区别。

标签: java bounds-check-elimination


【解决方案1】:

对于您的第一个问题,在示例 1 中,可以理论上消除边界检查。我希望最好的现代 JIT 编译器能够做到这一点(例如,当 source[index] 扩展时,可能通过边界检查中的公共子表达式消除)。像往常一样,这将取决于实现,因此您不能依赖它。 OTOH,即使没有消除边界检查,差异也将是微不足道的 - 您正在访问 source.length 的已缓存内存位置并进行几个整数比较,因此开销很小。

example2 不是一个好习惯——你遇到了一个异常,然后捕获它并继续,好像什么都没发生一样。除非您密切关注标准输出,否则您可能会完全忽略代码中存在错误的事实。

根据您认为“索引”的有效输入,基本上有两种常见的“好”可能性:

  1. 越界索引值为 预期,并被视为有效输入。在 哪种情况你应该测试和处理它 明确地如示例 1 所示。在这种情况下,您不需要抛出任何类型的异常。

  2. 超出范围的索引是意外的(因此是调用代码中的错误)。您的代码应在此处引发异常。如果您愿意,您可以使用自己的消息捕获并重新抛出异常,但您也可以让 IndexOutOfBounds 异常传播。不要担心这种异常处理对性能的影响——您刚刚发现了一个错误,因此您希望程序尽可能快地“大声”地失败.....

【讨论】:

  • 好答案。但我认为打印到标准输出只是为了演示不同的用例。
【解决方案2】:

我看不出索引越界怎么可能是正常情况。您的算法有错误,或者您没有正确验证输入。在这种情况下,验证输入包括检查索引是否在边界内。使用if(如在您的第一个 sn-p 中)检查它显然比捕获异常更具可读性、简洁性和效率。

【讨论】:

  • 当您解码网络数据包时,数组的索引通常是根据数据包本身的数据计算得出的,这些数据可能已损坏。代码需要优雅地处理格式错误的数据包。在 C 代码中不这样做通常是许多安全漏洞的基础。
  • 是的。这就是我所说的“验证输入”。这里的输入是根据数据计算的索引。如果您必须优雅地处理损坏的数据包,请检查索引是否在界限内,并采取相应措施。但是检查应该使用 if 语句来实现,而不是通过捕获 IndexOutOfBoundsException。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-19
  • 2016-05-25
  • 2011-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多