修改:这是不关于微基准测试的一般问题。我知道垃圾收集器是不可预测的。我想知道如何在这个特定的情况下,单个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.");
}
}
对于如此长的示例代码感到抱歉,但是任何更小的示例代码都不会引发奇怪。 (我花了近两个小时尝试用更少的代码重现,这是我能做的最好的。)
任何想法?!?我在这里疯了。