为什么这个print语句会将代码的其余部分减慢4倍?

时间:2016-06-28 06:26:30

标签: java performance

修改:这是关于微基准测试的一般问题。我知道垃圾收集器是不可预测的。我想知道如何在这个特定的情况下,单个toString()数组的.length属性可能如此可靠地在多个JVM上导致这种更改。

原始问题如下:

我是一名高中老师。我试图将一个小例子放在一起向我的学生们展示基元数组比Integer对象数组稍微有效一些。此示例程序为我提供了意外的输出。

50000 objects...    sorted in 1377 ms.
50000 primitives... sorted in 2565 ms.

但是,如果我删除一个print语句(通过切换布尔值),我得到:

50000 objects...    sorted in 1444 ms.
50000 primitives... sorted in 772 ms.

(当然,有问题的印刷语句不在循环内。)

当减速有效时,改变测试的顺序(首先是基元,然后是对象),这样就可以使得SECOND减速时发生:

50000 primitives... sorted in 775 ms.
50000 objects...    sorted in 3640 ms.

在两个循环之间添加延迟也“修复”了减速。

我尝试在两者之间添加System.gc()而不是延迟,但它没有帮助。

我也尝试了多个JRE,我在Oracle的1.8.0_31和OpenJDK的1.8.0_91上获得了类似的输出。它在IDEOne上超时,因为它需要超过5秒,但较小的数组大小不会在IDEOne上出现错误。

public class PrintSlowdown {
    public static void main( String[] args ) {
        int[]     prims = new int[50000];
        Integer[] objs  = new Integer[prims.length];
        long start, stop;

        boolean slowDown = true;
        boolean compensate = false;

        // initialize both
        for ( int i=0; i<prims.length; i++ ) {
            prims[i] = (int)(Math.random()*1000);
            objs[i] = new Integer(prims[i]);
        }

        // Objects
        if ( slowDown )
            System.out.print(objs.length + " objects...    "); // WHY?!?
        else
            System.out.print("50000 objects...    ");
        start = System.nanoTime();
        for ( int i=0; i<objs.length-1; i++ ) {
            int min = i;
            for ( int j=i+1; j<objs.length; j++ ) {
                if ( objs[j].compareTo(objs[min]) < 0 )
                    min = j;
            }
            if ( min != i ) {
                Integer temp = objs[i];
                objs[i] = objs[min];
                objs[min] = temp;
            }
        }
        stop = System.nanoTime();
        System.out.println("sorted in " + (stop-start)/1000000 + " ms.");

        if ( compensate )
            try { Thread.sleep(2000); } catch (Exception e) {}

        // Primitives
        System.out.print(prims.length + " primitives... ");
        //System.out.print("primitives... ");
        start = System.nanoTime();
        for ( int i=0; i<prims.length-1; i++ ) {
            int min = i;
            for ( int j=i+1; j<prims.length; j++ ) {
            if ( prims[j] < prims[min] )
                min = j;
            }
            if ( min != i ) {
                int temp = prims[i];
                prims[i] = prims[min];
                prims[min] = temp;
            }
        }
        stop = System.nanoTime();
        System.out.println("sorted in " + (stop-start)/1000000 + " ms.");
    }
}

对于如此长的示例代码感到抱歉,但是任何更小的示例代码都不会引发奇怪。 (我花了近两个小时尝试用更少的代码重现,这是我能做的最好的。)

任何想法?!?我在这里疯了。

0 个答案:

没有答案