我正在使用junit运行这样的原始基准:
@Test
public void testTime() throws Exception{
LoadoutBase<?> loadout = new LoadoutStandard("AS7-D-DC");
final int iterations = 1000000;
long start = System.nanoTime();
int sum = 0;
for(int i = 0; i < iterations; ++i){
Iterator<Item> it = loadout.iterator();
while( it.hasNext() ){
sum += it.next().getNumCriticalSlots();
}
}
long end = System.nanoTime();
long time_it = end - start;
start = System.nanoTime();
sum = 0;
for(int i = 0; i < iterations; ++i){
for(Item item : loadout.getAllItems()){
sum += item.getNumCriticalSlots();
}
}
end = System.nanoTime();
long time_arrays = end - start;
System.out.println("it: " + time_it + " array: " + time_arrays + " diff: " + (double)time_it/time_arrays);
}
如果我设置iterations=1000000
,那么我会
it:792771504数组:1109215387差异:0.7147137637029551
非常一致,但如果我设置iterations=10000
,那么我得到
it:32365742 array:28902811 diff:1.1198129482976587
波动很大。 diff参数从0.7到1.2
有没有人能够了解这里可能发生的事情?我应该选择哪种方法?
我真正的基准测试是幕后工作。 getAllItems
创建一个新的List<Item>
,并使用addAll
获取16个子列表中的所有项目来填充它。 Iterator
方法不构造此临时列表,而是跟踪它当前正在迭代的这16个子列表中的哪一个,并且具有一些逻辑以使16个子列表看起来像连续列表。
答案 0 :(得分:4)
由于您要测试使用Iterator
和使用增强型for循环(在幕后为您使用Iterator
)之间的区别,然后您做错了。首先是因为JIT有足够的时间来改进第二种方法的结果,而不是第一种和其他几种原因:How do I write a correct micro-benchmark in Java?。你可以通过这些来看到非常不同的结果(再次,作为JIT的结果):
for
循环。for
循环方法之前执行。获得测试真实结果的最佳方法是将方法分成不同的方法,然后测量每个方法(除了JVM预热阶段和上一个QA中涵盖的其他内容)。另外,我建议你不要重新发明轮子并使用基于JUnit的适当基准框架。以下是其中两个:
相关问答/基准测试:
答案 1 :(得分:0)
在阅读了Luiggi Mendoza的链接后,我重构了我的测试代码:
@Test
public void testTime() throws Exception{
LoadoutBase<?> loadout = new LoadoutStandard("AS7-D-DC");
long start, end, sum;
final int iterations = 10000;
//WARMUP
start = System.nanoTime();
sum = 0;
for(int i = 0; i < iterations; ++i){
Iterator<Item> it = loadout.iterator();
while( it.hasNext() ){
sum += it.next().getNumCriticalSlots();
}
}
end = System.nanoTime();
//ENDOF WARMUP
start = System.nanoTime();
sum = 0;
for(int i = 0; i < iterations; ++i){
Iterator<Item> it = loadout.iterator();
while( it.hasNext() ){
sum += it.next().getNumCriticalSlots();
}
}
end = System.nanoTime();
long time_it = end - start;
// WARMUP
start = System.nanoTime();
sum = 0;
for(int i = 0; i < iterations; ++i){
for(Item item : loadout.getAllItems()){
sum += item.getNumCriticalSlots();
}
}
end = System.nanoTime();
// ENDOF WARMUP
start = System.nanoTime();
sum = 0;
for(int i = 0; i < iterations; ++i){
for(Item item : loadout.getAllItems()){
sum += item.getNumCriticalSlots();
}
}
end = System.nanoTime();
long time_arrays = end - start;
System.out.println("it: " + time_it + " array: " + time_arrays + " diff: " + (double)time_it/time_arrays);
}
现在我得到了一致的结果,说迭代器方法大约是getAllItems
方法执行速度的0.7倍。即使我改变测试的顺序,结果也是一致的,所以我相信他们的测试。
感谢。