Java条件运算符速度与热点虚拟机的版本

时间:2009-09-05 10:03:12

标签: java performance jvm jvm-hotspot

请考虑以下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;
}

}

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解释为字节码的方式。))它还有更多吗?
  • 其次。查看不同热点虚拟机的差异。见底部。这是因为VM的版本更新/改进了吗?或者还有更多吗?
  • 这是测试此类内容的最佳方式吗?

---结果Mac OS X ---

JavaVM HotSpot 1.6.0

Avr for Not Equals Operator: 1937
Avr for Equals“false”运算符: 1937
Avr for Not Operator: 1941

JavaVM HotSpot 1.5.0

Avr for Not Equals Operator: 5023
Avr for Equals“false”运算符: 5035
Avr for Not Operator: 5067

JavaVM HotSpot 1.4.2

Avr for Not Equals Operator: 3993
Avr for Equals“false”运算符: 4015
Avr for Not Operator: 4009

JavaVM HotSpot 1.4.0

Avr for Not Equals Operator: 3961
Avr for Equals“false”运算符: 3960
Avr for Not Operator: 3961

感谢。

3 个答案:

答案 0 :(得分:4)

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

然而,使用JVM版本的改进几乎肯定是真实的,尽管它可能非常特定于特定的代码片段,这是属于复杂性阈值的一些事情,需要正确处理。甚至略有不同的东西可能不会显示相同的结果。

要改进测试,请计算每次测试运行的standard deviation,看看它们是否在统计上有所不同(或者只是打印出所有10个结果并注视它们)。

答案 1 :(得分:2)

像这样的微型车标记并没有告诉你任何有趣的事情。您正在进行十亿次迭代测试,结果可在几秒钟内恢复。每次迭代有多少个周期?微基准测试没有做任何工作。

答案 2 :(得分:2)

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

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

换句话说,你的基准测试可能没有测量三种情况下的任何不同。

要学习的经验教训:

  1. 很难确定您是从微基准测试中获得有意义的数字。
  2. 从一个JVM到另一个JVM,相对数量可能会有很大差异。帮助一个JVM的“聪明技巧”实际上可能会阻碍另一个JVM。
  3. 编译器可能会为每个平台微优化Java程序做得更好。
  4. 最好的策略是将微优化留给编译器,并专注于使用最佳算法的“宏”问题。此外,使用执行分析器来确定值得花时间进行优化的地方。