美文网首页
JDK1.8 数组复制的效率测试

JDK1.8 数组复制的效率测试

作者: M_lear | 来源:发表于2019-02-26 14:52 被阅读0次

测试说明:

数组复制其实是很简单的操作,先分配内存再挨个赋值即可。但是 Java 源码却提供了一个复制数组的 native(本地)方法。
函数原型如下,位于 java.lang.System类当中:

public static native void arraycopy(Object src,  int  srcPos,
        Object dest, int destPos,
        int length);

那我就想了,这么简单的一个操作,究竟是自己去实现呢,还是调用 Java 自带的本地方法呢?
既然有了这样的选择,那当然是效率底下见真章了。

测试代码

基于 JDK1.8,分两次测试,第一次测试了数组长度为 100,1000 和 10000 三种情况,第二次测试了 50,100,1000,10000 四种情况,计时单位为纳秒(毫秒级上没差,所以有时也不用太过纠结)

public class Test {
    public static void main(String[] argus){
        //JDK 1.8
        int[] a50 = new int[50];
        int[] a100 = new int[100];
        int[] a1000 = new int[1000];
        int[] a10000 = new int[10000];
        long t1,t2,t3;
        //长度为50时的效率对比
//      int[] b50 = new int[50];
//      t1 = System.nanoTime();
//      for(int i = 0; i < b50.length; ++i){
//          b50[i] = a50[i];
//      }
//      t2 = System.nanoTime();
//      System.arraycopy(a50, 0, b50, 0, a50.length);
//      t3 = System.nanoTime();
//      System.out.println("数组长度为50时效率测试:");
//      System.out.println("自己复制:"+(t2-t1));
//      System.out.println("本地方法复制:"+(t3-t2));
        //长度为100时的效率对比
        int[] b100 = new int[100];
        t1 = System.nanoTime();
        for(int i = 0; i < b100.length; ++i){
            b100[i] = a100[i];
        }
        t2 = System.nanoTime();
        System.arraycopy(a100, 0, b100, 0, a100.length);
        t3 = System.nanoTime();
        System.out.println("数组长度为100时效率测试:");
        System.out.println("自己复制:"+(t2-t1));
        System.out.println("本地方法复制:"+(t3-t2));
        //长度为1000时的效率对比
        int[] b1000 = new int[1000];
        t1 = System.nanoTime();
        for(int i = 0; i < b1000.length; ++i){
            b1000[i] = a1000[i];
        }
        t2 = System.nanoTime();
        System.arraycopy(a1000, 0, b1000, 0, a1000.length);
        t3 = System.nanoTime();
        System.out.println("数组长度为1000时效率测试:");
        System.out.println("自己复制:"+(t2-t1));
        System.out.println("本地方法复制:"+(t3-t2));
        //长度为10000时的效率对比
        int[] b10000 = new int[10000];
        t1 = System.nanoTime();
        for(int i = 0; i < b10000.length; ++i){
            b10000[i] = a10000[i];
        }
        t2 = System.nanoTime();
        System.arraycopy(a10000, 0, b10000, 0, a10000.length);
        t3 = System.nanoTime();
        System.out.println("数组长度为10000时效率测试:");
        System.out.println("自己复制:"+(t2-t1));
        System.out.println("本地方法复制:"+(t3-t2));
    }
}

代码运行结果

上面代码的运行结果如下:


image.png

如果将长度为 50 的情况解注释,运行情况如下:


image.png

结论

在我只测试 100,1000,10000 三种情况时,我以为 native 方法在数组长度较短时表现不好,而在数组长度较长时明显优于自己写代码复制。但当我加入 50 这种情况时,我发现我错了。我猜测是 native 方法仅在第一次复制时运行时间较长(可能初始时需要配置资源),之后再运行速度均明显快于自己写循环复制。

下面我将在做一组横向对比来验证猜想,运行四次 1000 的情况:

public class Test {
    public static void main(String[] argus){
        //JDK 1.8
        int[] a1000 = new int[1000];
        int[] b1000 = new int[1000];
        int[] c1000 = new int[1000];
        int[] d1000 = new int[1000];
        int[] e1000 = new int[1000];//复制到此数组
        long t1,t2,t3;
        //长度为1000时的效率对比
        t1 = System.nanoTime();
        for(int i = 0; i < e1000.length; ++i){
            e1000[i] = a1000[i];
        }
        t2 = System.nanoTime();
        System.arraycopy(e1000, 0, a1000, 0, e1000.length);
        t3 = System.nanoTime();
        System.out.println("数组长度为1000时效率测试:");
        System.out.println("自己复制:"+(t2-t1));
        System.out.println("本地方法复制:"+(t3-t2));
        //长度为1000时的效率对比
        t1 = System.nanoTime();
        for(int i = 0; i < e1000.length; ++i){
            e1000[i] = b1000[i];
        }
        t2 = System.nanoTime();
        System.arraycopy(e1000, 0, b1000, 0, e1000.length);
        t3 = System.nanoTime();
        System.out.println("数组长度为1000时效率测试:");
        System.out.println("自己复制:"+(t2-t1));
        System.out.println("本地方法复制:"+(t3-t2));
        //长度为1000时的效率对比
        t1 = System.nanoTime();
        for(int i = 0; i < e1000.length; ++i){
            e1000[i] = c1000[i];
        }
        t2 = System.nanoTime();
        System.arraycopy(e1000, 0, c1000, 0, e1000.length);
        t3 = System.nanoTime();
        System.out.println("数组长度为1000时效率测试:");
        System.out.println("自己复制:"+(t2-t1));
        System.out.println("本地方法复制:"+(t3-t2));
        //长度为1000时的效率对比
        t1 = System.nanoTime();
        for(int i = 0; i < e1000.length; ++i){
            e1000[i] = d1000[i];
        }
        t2 = System.nanoTime();
        System.arraycopy(e1000, 0, d1000, 0, e1000.length);
        t3 = System.nanoTime();
        System.out.println("数组长度为1000时效率测试:");
        System.out.println("自己复制:"+(t2-t1));
        System.out.println("本地方法复制:"+(t3-t2));
    }
}

运行结果如下:


image.png

所以确实是 native 方法在第一次运行时可能需要进行资源配置,稍费一些时间,但在数组长度较长时,依然快于自己写代码复制。所以当我们的程序需要进行多次的大数组复制时,推荐调用 native(本地)方法去复制,效率较高。

相关文章

网友评论

      本文标题:JDK1.8 数组复制的效率测试

      本文链接:https://www.haomeiwen.com/subject/dbtayqtx.html