0

请考虑以下java源:

package com.stackoverflow;

 public class CondSpeed {
 private static final long COUNT = 1000000000;
 private static final long OUTER_COUNT = 15;

 private static long notEqOperator = 0L;
  private static long notOperator = 0L;
private static long equalsFalse = 0L;

public CondSpeed() {
 super();
}

public static void main(String[] args) {

 for(int outCount = 0;outCount < OUTER_COUNT;outCount++){
  notEqOperator += testNotEaualsOperator();
  equalsFalse += testEqualFalse();
  notOperator += testNotOperator();
 }

 long avrForNotEqOperator = (notEqOperator / OUTER_COUNT);
 long avrForEqualsFalse = (equalsFalse / OUTER_COUNT);
 long avrForNotOperator = (notOperator / OUTER_COUNT);

 System.out.println("Avr for Not Equals Operator: "+avrForNotEqOperator);
 System.out.println("Avr for Equals \"false\" Operator: "+avrForEqualsFalse);
 System.out.println("Avr for Not Operator: "+avrForNotOperator);

}

private static long testEqualFalse(){
 long now = System.currentTimeMillis();

 for(long i = 0;i < COUNT;i++){
  boolean truFalse = returnTrueOrFalse();

  if(truFalse == false){
   //do nothing...
  }
 }

 return (System.currentTimeMillis() - now);
}


   private static long testNotOperator(){
 long now = System.currentTimeMillis();

 for(long i = 0;i < COUNT;i++){
  boolean truFalse = returnTrueOrFalse();

  if(!truFalse){
//do nothing...
  }
 }

 return (System.currentTimeMillis() - now);
}

private static long testNotEaualsOperator(){
 long now = System.currentTimeMillis();

 for(long i = 0;i < COUNT;i++){
  boolean truFalse = returnTrueOrFalse();

  if(truFalse != true){
   //do nothing...
  }
 }

 return (System.currentTimeMillis() - now);
}

private static boolean isFalse;
private static boolean returnTrueOrFalse(){
 if(isFalse){
  isFalse = false;
 }
 else{
  isFalse = true;
 }
 return isFalse;
}

}

如您所见,这是针对 3 个版本的if(false)条件的测试。

  • 我对为什么结果首先在各种条件语句中不同感兴趣。((我知道这显然是编译器将 .java 解释为字节码的方式。))还有比这更多的吗?
  • 第二。查看不同 Hotspot VM 的差异。见底部。这是因为更新/改进了虚拟机的版本吗?或者还有更多?
  • 这是测试这样的东西的最好方法吗?

---结果 Mac OS X---

JavaVM 热点 1.6.0

不等于运算符的 Avr:1937
等于“假”运算符的 Avr:1937
非运算符的 Avr:1941

JavaVM 热点 1.5.0

不等于运算符的 Avr:5023
等于“假”运算符的 Avr:5035
非运算符的 Avr:5067

JavaVM 热点 1.4.2

不等于运算符的 Avr:3993
等于“假”运算符的 Avr:4015
非运算符的 Avr:4009

JavaVM 热点 1.4.0

不等于运算符的 Avr:3961
等于“假”运算符的 Avr:3960
非运算符的 Avr:3961

谢谢。

4

3 回答 3

4

!, != 和 == 之间的差异看起来像随机噪音 - 你真的希望它们出现完全相同的毫秒数吗?

然而,JVM 版本的改进几乎可以肯定是真实的,尽管它可能非常特定于那段特定的代码,这是一个属于需要正确处理的复杂性阈值的问题。即使略有不同,也可能不会显示相同的结果。

为了改进测试,计算每个测试运行的标准偏差,看看它们在统计上是否不同(或者只是打印出所有 10 个结果并观察它们)。

于 2009-09-05T10:31:32.483 回答
2

像这样的微基准不会告诉你任何有趣的事情。您正在执行十亿次测试迭代,结果会在几秒钟内返回。每次迭代有多少个周期?微基准没有做任何工作。

于 2009-09-05T10:21:01.600 回答
2

如果 JVM 做得不错,它将检测到以下语句不会影响计算,并将完全优化它们。

if (truFalse != true) {
     //do nothing...
}
...
if (truFalse == false) {
   //do nothing...
}
...
if (!truFalse) {
   //do nothing...
}

换句话说,您的基准测试可能在这三种情况下没有衡量任何不同之处。

教训:

  1. 很难确定您从微基准测试中获得了有意义的数字。
  2. 从一个 JVM 到另一个 JVM,相对数字可能会有很大差异。一个有助于一个 JVM 的“聪明的技巧”实际上可能会妨碍另一个 JVM。
  3. 在为每个平台优化 Java 程序方面,编译器可能比你做得更好。

最好的策略是将微优化留给编译器,专注于“宏观”问题,比如使用最佳算法。此外,使用执行分析器找出值得花时间优化的地方。

于 2009-09-05T13:20:48.283 回答