Java边界检查优化示例

时间:2011-07-03 15:58:04

标签: java bounds-check-elimination

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

在下面的方法 example1 中,JVM会想出来并消除 source [index] 引用的边界检查吗?

example2 更好的代码练习?看起来似乎如此,但在循环内的一些算法中,索引超出界限是正常情况。因此,您不希望在该循环中生成大量的Exception对象。

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);
    }
}

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

2 个答案:

答案 0 :(得分:5)

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

example2不是一个好习惯 - 你正在点击一个例外,然后抓住它并继续,好像什么也没发生。除非你仔细观察stdout,否则你可能会完全错过你的代码中存在错误的事实。

基本上有两种常见的“好”可能性取决于你认为是“索引”的有效输入:

  1. 越界索引值是 预期并被视为有效输入。在 在哪种情况下你应该测试和处理它 显式如example1。在这种情况下,您不需要抛出任何异常。

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

答案 1 :(得分:2)

我不知道索引如何超出界限可能是正常情况。您的算法有错误,或者您没有正确验证输入。在这种情况下,验证输入包括检查索引是否在边界内。使用if(与第一个代码段相同)进行检查显然比捕获异常更具可读性,清晰度和效率。