Optimizing Boolean Expressions in Java Baeldung

Consider the following method in Java:

public static boolean expensiveComputation() {
    for (int i = 0; i < Integer.MAX_VALUE; ++i);
    return false;
}

      

And the following main method:

public static void main(String[] args) {
    boolean b = false;
    if (expensiveComputation() && b) {
    }
}

      

Logical join (same as & &) is a commutative operation . So, why does the compiler not optimize the if-statement to the equivalent:

if (b && expensiveComputation()) {
}

      

which has the advantages of using short circuit evaluation ?

Also, is the compiler trying to do other boolean simplifications or boolean rearrangements to generate faster code? If not, why not? Of course some optimizations will be very tricky, but my example is not simple? A method call should always be slower than reading a boolean, right?

Thanks in advance.

+2


source to share


5 answers


This is not the case, because the expensive Comput () can have side effects that change the state of the program. This means that the order in which expressions in boolean operators (costComput () and b) are evaluated does matter. You don't want the compiler to optimize the error in your compiled program, do you?

For example, what if the code looked like



public static boolean expensiveComputation() {
        for (int i = 0; i < Integer.MAX_VALUE; ++i);
        b = false;
        return false;
}

public static boolean b = true;
public static void main(String[] args) {
        if (expensiveComputation() || b) {
        // do stuff
        }
}

      

Here, if the compiler has done your optimization, then it //do stuff

will execute when you don't expect it by looking at the code (since b is evaluated first, which is initially true).

+15


source


Because it expensiveComputation()

can have side effects.

Since Java does not strive to be a functionally pure language, this does not prevent programmers from writing methods that have side effects. So there probably isn't much value in compiler analysis for functional purity. And then the optimization, as you think, is unlikely to be very valuable in practice, since it expensiveComputation()

usually needs to be done anyway in order to get side effects.



Of course, it is easy for a programmer to put it first b

if they expect it to be false and clearly want to avoid costly computation.

+8


source


Actually, some compilers can optimize programs like the one you suggested, you just need to make sure that the function has no side effects. GCC has a compiler directive that you can annotate a function to show that it has no side effects that the compiler can use when optimizing. Java might have something like this.

A classic example:

for (ii = 0; strlen (s)> ii; ii ++) <do something>

which is optimized for

n = strlen (s); for (ii = 0; n> ii; ii ++) do something>

GCC with optimization level 2, at least on my machine.

+2


source


The compiler will optimize this if you run your code often enough, perhaps by nesting the method and simplifying the resulting boolean expression (but most likely not by reordering the & & arguments).

You can compare this by counting the loop as repeating a million iterations of this code. The first iteration or two is much slower than the next.

0


source


The java version I'm using optimizes a in expression a && b

, but not with b.

i.e. If a is false, b is not evaluated, but if b was false, it was not.

I found this out when I was doing validation on a website form: I created posts to display on a web page in a series of boolean methods. I expected fields on the page that were incorrectly entered to get highlighted, but due to Java negligence, the code was only executed until the first incorrect field was found. After that Java must have thought something like "false && any always always" and left out the rest of the validation methods.

I suppose as a direct answer to your question, if you do this kind of optimization, your program might run slower than it could. However, someone else's program will break completely because they adopted unoptimized behavior as a side effect mentioned in other answers.

Unfortunately, it is difficult to automate smart decisions, especially with imperative languages ​​(C, C ++, Java, Python, ... i.e. normal languages).

0


source







All Articles