Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的布尔表达式优化_Java_Optimization_Compiler Construction_Boolean Logic_Boolean Expression - Fatal编程技术网

Java中的布尔表达式优化

Java中的布尔表达式优化,java,optimization,compiler-construction,boolean-logic,boolean-expression,Java,Optimization,Compiler Construction,Boolean Logic,Boolean Expression,考虑Java中的以下方法: public static boolean expensiveComputation() { for (int i = 0; i < Integer.MAX_VALUE; ++i); return false; } 逻辑连词(与&&)是一个。那么,编译器为什么不将if语句代码优化为等效代码呢 if (b && expensiveComputation()) { } 哪一个有最好的 此外,编译器是否尝试进行其他逻辑简化或布尔值排

考虑Java中的以下方法:

public static boolean expensiveComputation() {
    for (int i = 0; i < Integer.MAX_VALUE; ++i);
    return false;
}
逻辑连词(与&&)是一个。那么,编译器为什么不将if语句代码优化为等效代码呢

if (b && expensiveComputation()) {
}
哪一个有最好的

此外,编译器是否尝试进行其他逻辑简化或布尔值排列,以生成更快的代码?若否,原因为何?当然,一些优化会非常困难,但我的示例并不简单?调用方法应该总是比读取布尔值慢,对吗


提前谢谢。

它不会这样做,因为expensiveComputation()可能会产生副作用,从而改变程序的状态。这意味着布尔语句中表达式的求值顺序(expensiveComputation()和b)很重要。你不会希望编译器在你编译的程序中优化一个bug吧

例如,如果代码是这样的呢

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
        }
}
公共静态布尔运算(){
对于(int i=0;i

在这里,如果编译器执行了您的优化,那么通过查看代码,
//do stuff
将在您不希望它运行的时候运行(因为最初为true的b将首先计算)。

因为
expensiveComputation()
可能会产生副作用

由于Java的目标不是成为一种功能上纯粹的语言,因此它并不禁止程序员编写有副作用的方法。因此,编译器分析函数纯度可能没有太大价值。然后,像您所假设的优化在实践中不太可能有价值,因为通常需要执行
expensiveComputation()
,以获得副作用


当然,对于程序员来说,如果他们认为
b
是错误的,并且明确希望避免昂贵的计算,那么很容易将其放在第一位。

如果您足够频繁地运行代码,编译器将对此进行优化,可能是通过内联方法和简化生成的布尔表达式(但很可能不是通过对&&的参数重新排序)

您可以通过对该代码的循环(例如一百万次迭代)进行重复计时来对此进行基准测试。第一次迭代或第二次迭代比下面的迭代慢得多。

实际上,有些编译器可以像您建议的那样优化程序,只需确保函数没有副作用。GCC有一个编译器指令,您可以对其进行注释一个函数,用于显示它没有副作用,编译器可以在优化时使用它。Java可能有类似的功能

一个典型的例子是

对于(ii=0;strlen>ii;ii++)

这将优化为

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


至少在我的机器上,通过GCC和优化级别2进行优化。

我使用的java版本在表达式
a和&b中优化a,但不使用b

i、 e.如果a为假,b不会得到评估,但如果b为假,则不会得到评估

当我在一个网站表单中实现验证时,我发现了这一点:我创建了消息,以一系列布尔方法显示在网页上。 我希望页面中输入错误的字段会突出显示,但是,由于Java的速度攻击,代码只在发现第一个错误字段之前执行。此后,Java一定认为“false&&任何东西都是false”之类的内容,并跳过了剩余的验证方法

我想,作为对你问题的直接回答,如果你进行这样的优化,你的程序可能会运行得比可能的慢。但是,其他人的程序将完全崩溃,因为他们假设了非优化行为,如其他答案中提到的副作用


遗憾的是,智能决策很难实现,特别是用命令语言(C,C++,java,python,即普通语言)。.

这是一个愚蠢的例子-它与| |有些不同。为什么不把副作用放在昂贵的计算中,这会很好地说明这一点。它与
| |
没有什么不同。同样的优化也可以完成,并且有同样的含义。这只是我想到的第一个例子一个立即可以注意到的效果,这与他的例子有关。JVM或javac是否真的做到了这一点?或者你说的是某个理论抽象层?是的,JVM包含一个优化的即时编译器,它编译大量使用的代码。我做了那个基准测试,第一次迭代需要10毫秒,第二次迭代需要5毫秒,之后就是10毫秒每次迭代只显示零时间。@starblue:我认为编译器不允许对LHS和RHS表达式的计算进行重新排序,除非可以证明优化不会改变计算结果。不,编译器不需要重新排序。内联后,它将看到布尔常量和optimi将&&away.设置为零,这并不能避免费用调用
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
        }
}