简体   繁体   English

java编译器可以优化循环以尽早返回吗?

[英]Can the java compiler optimize loops to return early?

I'm working with an external library that decided to handle collections on its own. 我正在使用一个外部库,决定自己处理集合。 Not working with it or updating is outside my control. 不使用它或更新是我无法控制的。 To work with elements of this third party "collection" it only returns iterators. 要使用此第三方“集合”的元素,它只返回迭代器。

A question came up during a code review about having multiple returns in the code to gain performance. 在代码审查期间出现了一个问题,即在代码中有多个返回以获得性能。 We all agree (within the team) the code is more readable with a single return, but some are worried about optimizations. 我们都同意(在团队内部)代码在单次返回时更具可读性,但有些人担心优化。

I'm aware premature optimization is bad. 我知道过早的优化很糟糕。 That is a topic for another day. 这是另一天的话题。

I believe the JIT compiler can handle this and skip the unneeded iterations, but could not find any info to back this up. 我相信JIT编译器可以处理这个并跳过不需要的迭代,但找不到任何信息来支持它。 Is JIT capable of such a thing? JIT能胜任这样吗?

A code sample of the issue at hand: 手头问题的代码示例:

public void boolean contains(MyThings things, String valueToFind) {
    Iterator<Thing> thingIterator = things.iterator();
    boolean valueFound = false;
    while(thingIterator.hasNext()) {
        Thing thing = thingIterator.next();
        if (valueToFind.equals(thing.getValue())) {
            valueFound = true;
        }
    }
    return valueFound;
}

VS VS

public void boolean contains(MyThings things, String valueToFind) {
    Iterator<Thing> thingIterator = things.iterator();
    while(thingIterator.hasNext()) {
        Thing thing = thingIterator.next();
        if (valueToFind.equals(thing.getValue())) {
            return true;
        }
    }
    return false;
}

We all agree the code is more readable with a single return. 我们都同意代码在单次返回时更具可读性。

Not really. 并不是的。 This is just old school structured programming when functions were typically not kept small and the paradigms of keeping values immutable weren't popular yet. 这只是旧式的结构化编程,当函数通常不会很小并且保持值不可变的范例还不流行。

Although subject to debate, there is nothing wrong with having very small methods (a handful of lines of code), which return at different points. 尽管存在争议,但是使用非常小的方法(少量代码行)并没有错,这些方法在不同的点返回。 For example, in recursive methods, you typically have at least one base case which returns immediately, and another one which returns the value returned by the recursive call. 例如,在递归方法中,通常至少有一个基本情况立即返回,另一个返回递归调用返回的值。

Often you will find that creating an extra result variable, just to hold the return value, and then making sure no other part of the function overwrites the result, when you already know you can just return, just creates noise which makes it less readable not more. 通常你会发现创建一个额外的结果变量,只是为了保存返回值,然后确保函数的其他部分没有覆盖结果,当你已经知道你可以返回时,只是产生噪声,这使得它不易读取更多。 The reader has to deal with cognitive overload to see the result is not modified further down. 读者必须处理认知过载才能看到结果未被进一步修改。 During debugging this increases the pain even more. 在调试期间,这会进一步增加疼痛。

I don't think your example is premature optimisation. 我不认为你的例子是过早的优化。 It is a logical and critical part of your search algorithm. 它是搜索算法的逻辑和关键部分。 That is why you can break from loops, or in your case, just return the value. 这就是为什么你可以从循环break ,或者在你的情况下,只返回值。 I don't think the JIT could realise that easily it should break out the loop. 我不认为JIT可以很容易地意识到它应该打破循环。 It doesn't know if you want to change the variable back to false if you find something else in the collection. 如果您在集合中找到其他内容,则不知道是否要将变量更改回false (I don't think it is that smart to realise that valueFound doesn't change back to false ). (我不认为认识到valueFound不会变回false是那么聪明)。

In my opinion, your second example is not only more readable (the valueFound variable is just extra noise) but also faster, because it just returns when it does its job. 在我看来,你的第二个例子不仅更具可读性( valueFound变量只是额外的噪音)而且更快,因为它只是在它完成工作时返回。 The first example would be as fast if you put a break after setting valueFound = true . 如果在设置valueFound = true后放置一个break ,第一个例子会很快。 If you don't do this, and you have a million items to check, and the item you need is the first, you will be comparing all the others just for nothing. 如果你不这样做,并且你需要检查一百万件物品,并且你需要的物品是第一件物品,那么你将比较所有其他物品。

Java compiler cannot do an optimization like that, because doing so in a general case would change the logic of the program. Java编译器不能像这样进行优化,因为在一般情况下这样做会改变程序的逻辑。

Specifically, adding an early return would change the number of invocations of thingIterator.hasNext() , because your first code block continues iterating the collection to the end. 具体来说,添加早期返回将改变thingIterator.hasNext()的调用thingIterator.hasNext() ,因为您的第一个代码块会继续将集合迭代到最后。

Java could potentially replace a break with an early return, but that would have any effect on the timing of the program. Java可以用早期的返回来代替break ,但这会对程序的时间产生任何影响。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM