Java中假设存在一个2维数组
byte[][] byteArr;
int i,n;
byte a,d;
long lsum;请猜下面2段代码效率哪个高?
代码1                    a = byteArr[i][n];
                    
                    if(a > 0 && a < 10)
                        lsum += a;
代码2                    a = byteArr[i][n];
                    d = (byte)(Math.abs(a - 5));                    if(d < 5)
                        lsum += a;
以上在计算量超大的时候进行的测试。
如下测试代码        Random rnd = new Random();
        long lsum = 0;
        byte[][] byteArr = new byte[2000][1000];
        for(int i = 0; i < 2000; i++)
        {
            for(int n = 0; n < 1000; n++)
            {
                byteArr[i][n] = (byte)(rnd.nextInt());
            }
        }
        byte a = 0;
        byte d = 0;
        long t11 = new Date().getTime();
        for(int t = 0; t < 2000; t++)
        {
            for(int i = 0; i < 1000; i++)
            {
                for(int n = 0; n < 1000; n++)
                {
                    a = byteArr[i][n];
                    
                    if(a > 0 && a < 10)
                        lsum += a;
                }
            }
        }
        long t12 = new Date().getTime();
        long t21 = new Date().getTime();
        for(int t = 0; t < 2000; t++)
        {
            for(int i = 0; i < 1000; i++)
            {
                for(int n = 0; n < 1000; n++)
                {
                    a = byteArr[i][n];
                    d = (byte)(Math.abs(a - 5));                    if(d < 5)
                        lsum += a;
                }
            }
        }
        long t22 = new Date().getTime();        System.out.println("t11 - t12: " + (t12 - t11));
        System.out.println("t21 - t22: " + (t22 - t21));结果是第一段的执行时间几乎是第2段的2.5倍。本人对Java底层了解不深,特此求解。Java测试效率二维数组

解决方案 »

  1.   


    if(a > 0 && a < 10)
    这里进行的是两个判断,当然,&&是具有短路性的,第一个判断不成立时第二个直接跳过。所以应该比一个判断的效率低一些,但不会达到2倍的程度。if(d < 5)这里就一个判断,效率自然应该高一些。所以我感觉8比5的时间在理论上讲也许更适合一些。
      

  2.   

    第二段的效率肯定没有第一段的高哇, d = (byte)(Math.abs(a - 5));这句话执行也是要花时间的哇,第一段先比较后才执行,第二段不管怎么样,首先来执行了 d = (byte)(Math.abs(a - 5));
      

  3.   

    上面比下面的执行时间短,下面的方法会使用math的abs方法,比起单纯的双判断占用资源更小,执行更有效率还有,一般人都会使用上面的方法判断吧,为什么有人会使用下面哪种让人推敲一会儿的方式去实现
      

  4.   

    换台机器以后正常,时间5:8左右
    环境是
    dual-CORE E5800
    WIN XP 32位 SP3
    4G 内存
    JAVA 1.6先前测试时间是2.5:1
    环境是
    I7 3770
    WIN 7 64位
    8G内存
    JAVA 1.7
      

  5.   

    前后时间也差非常多
    I7用时大概是6.5s : 2.8sdual用时大概是24.5s : 40.3s
      

  6.   

    第一段效率高。Math.abs也不是什么神奇的函数,也是要判断的,JDK里的代码:
        public static int abs(int a) {
            return (a < 0) ? -a : a;
        }
    这里做了一次判断,而且做了一次"-"运算。abs的消耗更大一些。这里的结果第一段慢,是因为你的测试是错的。byteArr里如果有一个比如说-125,那么-125 - 5 = -130,abs(-130) = 130,(byte) 130 = -126,于是-125被错误地加入了lsum。如果你把
    byte d = 0;
    d = (byte)(Math.abs(a - 5));改成int d = 0;
    d = Math.abs(a - 5);那两段代码测试结果应该是相似的,而且第一段略快一些。至于你要问,为什么错的时候快的那段代码反而是lsum+=a执行得多的那段,我便不能解释了。也许JVM在编译的时候预判c < 5的几率较大,所以直接执行c<5后的语句比调用一次branch更快?这个我真的是瞎猜,但是要测谁的性能好,前提是公平测试。改进过后的测试程序:
    import java.util.Random;class Test {
      private static byte[][] byteArr;  public static void main(final String[] args) {
        Random rnd = new Random();    byteArr = new byte[200][100];
        for (int i = 0; i < 200; i++) {
          for (int n = 0; n < 100; n++) {
            byteArr[i][n] = (byte) (rnd.nextInt());
          }
        }    test1(10000); //warm up
        test2(10000); //warm up    test1(1000);
        test2(1000);    test2(1000);
        test1(1000);    test1(1000);
        test2(1000);    test2(1000);
        test1(1000);
      }  static void test1(int rounds) {
        long startTime = System.nanoTime();
        long sum = 0;
        for (int i = 0; i < rounds; i++) {
          sum = testRoutine1();
        }
        long endTime = System.nanoTime();
        System.out.println("Test1: " + (endTime - startTime) + " " + sum);
      }  static void test2(int rounds) {
        long sum = 0;
        long startTime = System.nanoTime();
        for (int i = 0; i < rounds; i++) {
          sum = testRoutine2();
        }
        long endTime = System.nanoTime();
        System.out.println("Test2: " + (endTime - startTime) + " " + sum);
      }  static long testRoutine1() {
        long lsum = 0;
        for (int i = 0; i < 200; i++) {
          for (int n = 0; n < 100; n++) {
            byte b = byteArr[i][n];
            int c = Math.abs(b - 5);
            if (c < 5) {
              lsum += b;
            }
          }
        }
        return lsum;
      }  static long testRoutine2() {
        long lsum = 0;
        for (int i = 0; i < 200; i++) {
          for (int n = 0; n < 100; n++) {
            byte b = byteArr[i][n];
            if (b > 0 && b < 10) {
              lsum += b;
            }
          }
        }
        return lsum;
      }
    }
      

  7.   


    之前测试的结果是第一段快,第二段慢,按照开始的解释应该第二段加操作多过第一段,且abs效率低,其实还是跟原先疑惑的情况不吻合的。不管如何,多谢费心解答