if(a&&b) 是否应该比 if(a) if(b) 花费更多时间?
Should if(a&&b) take more time than if(a) if(b)?
我使用以下简单逻辑来回答 question 像这样的问题:
1: if(a) // 1 operation
2: if (b) // 1 operation
和
1: if(a && b) // 1, 1(&&), 1 => 3 operations.
因此,2 个操作与 3 个操作相比,但在第一个示例中,编译器需要调用另一条指令来执行。
这个逻辑对吗?。
它取决于编译器吗?
仅调用 ;
之类的空指令是否会使编译器花费一些明显的时间?
This 也讨论了同样的问题,但没有考虑这个逻辑。
请帮助我们澄清这个问题。
有两种方法可以准确回答这样的问题:
1.) 查看 IL 代码 (and/or) 汇编代码生成并计算执行此代码所需的 CPU 周期(提示:这不适合初学者)
2.) 构建一个小的测试程序,它会多次执行这两种变体,使用 StopWatch() 创建一个有用且可读的计时输出,运行 多次。
3.) 猜猜你认为编译器的优化步骤能做什么,这个软件会做什么,和别人争论几个小时
有两种方法可以考虑您的问题:
Java 语言定义
- 语言定义第二个示例将使用短路执行,这意味着 在
if
语句将包含任何代码的情况下,第二个示例可能执行得更快
JVM优化
- JVM 运行时将删除死代码块,如果它可以证明它们没有任何副作用
我假设编译器会为您的两种情况生成相同的字节码。所以我用两个不同的源文件测试了这个:
public class Test1 {
public static void main(String[] args) {
if (args[0].equals("a"))
if (args[1].equals("b"))
System.out.println("Foo");
}
}
和...
public class Test2 {
public static void main(String[] args) {
if (args[0].equals("a") && args[1].equals("b"))
System.out.println("Foo");
}
}
用javap -c Test1
等检查他们的字节码,结果是一样的:
public static void main(java.lang.String[]);
Code:
0: aload_0
1: iconst_0
2: aaload
3: ldc #2 // String a
5: invokevirtual #3 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
8: ifeq 30
11: aload_0
12: iconst_1
13: aaload
14: ldc #4 // String b
16: invokevirtual #3 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
19: ifeq 30
22: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
25: ldc #6 // String Foo
27: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
30: return
因此,性能将是相同的。如果有人能想到生成不同字节码的示例,我欢迎发表评论。
我的结果使用的是来自 Java 1.7 的 Oracle javac
。结果可能与其他编译器不同,但我怀疑它们不会适用于这种情况。
我使用以下简单逻辑来回答 question 像这样的问题:
1: if(a) // 1 operation
2: if (b) // 1 operation
和
1: if(a && b) // 1, 1(&&), 1 => 3 operations.
因此,2 个操作与 3 个操作相比,但在第一个示例中,编译器需要调用另一条指令来执行。
这个逻辑对吗?。
它取决于编译器吗?
仅调用 ;
之类的空指令是否会使编译器花费一些明显的时间?
This 也讨论了同样的问题,但没有考虑这个逻辑。 请帮助我们澄清这个问题。
有两种方法可以准确回答这样的问题:
1.) 查看 IL 代码 (and/or) 汇编代码生成并计算执行此代码所需的 CPU 周期(提示:这不适合初学者)
2.) 构建一个小的测试程序,它会多次执行这两种变体,使用 StopWatch() 创建一个有用且可读的计时输出,运行 多次。
3.) 猜猜你认为编译器的优化步骤能做什么,这个软件会做什么,和别人争论几个小时
有两种方法可以考虑您的问题:
Java 语言定义
- 语言定义第二个示例将使用短路执行,这意味着 在
if
语句将包含任何代码的情况下,第二个示例可能执行得更快
- 语言定义第二个示例将使用短路执行,这意味着 在
JVM优化
- JVM 运行时将删除死代码块,如果它可以证明它们没有任何副作用
我假设编译器会为您的两种情况生成相同的字节码。所以我用两个不同的源文件测试了这个:
public class Test1 {
public static void main(String[] args) {
if (args[0].equals("a"))
if (args[1].equals("b"))
System.out.println("Foo");
}
}
和...
public class Test2 {
public static void main(String[] args) {
if (args[0].equals("a") && args[1].equals("b"))
System.out.println("Foo");
}
}
用javap -c Test1
等检查他们的字节码,结果是一样的:
public static void main(java.lang.String[]); Code: 0: aload_0 1: iconst_0 2: aaload 3: ldc #2 // String a 5: invokevirtual #3 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 8: ifeq 30 11: aload_0 12: iconst_1 13: aaload 14: ldc #4 // String b 16: invokevirtual #3 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 19: ifeq 30 22: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 25: ldc #6 // String Foo 27: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 30: return
因此,性能将是相同的。如果有人能想到生成不同字节码的示例,我欢迎发表评论。
我的结果使用的是来自 Java 1.7 的 Oracle javac
。结果可能与其他编译器不同,但我怀疑它们不会适用于这种情况。