代码之家  ›  专栏  ›  技术社区  ›  Koekiebox

Java条件运算符速度与热点VM版本

  •  0
  • Koekiebox  · 技术社区  · 16 年前

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

    if(false) 条件。

    • 我感兴趣的是为什么在各种条件陈述中,结果首先是不同的。((我知道这显然是编译器将.java解释为字节码的方式。)除此之外还有什么?
    • 这是测试此类内容的最佳方式吗?

    JavaVM热点1.6.0

    不等于运算符的Avr:

    JavaVM热点1.5.0

    不等于运算符的Avr: 5023
    5035
    非操作员Avr: 5067

    JavaVM热点1.4.2

    不等于运算符的Avr:
    4015
    非操作员Avr: 4009

    JavaVM热点1.4.0

    不等于运算符的Avr: 3961
    3960
    非操作员Avr: 3961

    谢谢。

    3 回复  |  直到 16 年前
        1
  •  4
  •   soru    16 年前

    之间的差异!,!=和==看起来像是随机噪声——你真的以为它们会输出完全相同的毫秒数吗?

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

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

        2
  •  2
  •   Tom Hawtin - tackline    16 年前

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

        3
  •  2
  •   Stephen C    16 年前

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

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

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

    经验教训:

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