性能测试独立于迭代次数
试图回答这张票:instanceof和Class.isAssignableFrom(...)有什么区别?
我做了一个性能测试:
class A{}
class B extends A{}
A b = new B();
void execute(){
boolean test = A.class.isAssignableFrom(b.getClass());
// boolean test = A.class.isInstance(b);
// boolean test = b instanceof A;
}
@Test
public void testPerf() {
// Warmup the code
for (int i = 0; i < 100; ++i)
execute();
// Time it
int count = 100000;
final long start = System.nanoTime();
for(int i=0; i<count; i++){
execute();
}
final long elapsed = System.nanoTime() - start;
System.out.println(count+" iterations took " + TimeUnit.NANOSECONDS.toMillis(elapsed) + "ms.);
}
哪给了我:
但是用迭代的次数来看,我可以看到性能是不变的。 对于Integer.MAX_VALUE:
认为这是一个编译器优化(我用JUnit运行这个测试),我将它改为:
@Test
public void testPerf() {
boolean test = false;
// Warmup the code
for (int i = 0; i < 100; ++i)
test |= b instanceof A;
// Time it
int count = Integer.MAX_VALUE;
final long start = System.nanoTime();
for(int i=0; i<count; i++){
test |= b instanceof A;
}
final long elapsed = System.nanoTime() - start;
System.out.println(count+" iterations took " + TimeUnit.NANOSECONDS.toMillis(elapsed) + "ms. AVG= " + TimeUnit.NANOSECONDS.toMillis(elapsed/count));
System.out.println(test);
}
但是性能仍然与迭代次数“独立”。 有人可以解释这种行为吗?
JIT编译器可以消除不起任何作用的循环。 这可以在10,000次迭代后触发。
我怀疑你的时机是JIT需要多长时间才能检测到循环没有做任何事情并将其删除。 这将比做10,000次迭代需要的时间长一点。
无论如何,我总是通过外部方法调用内部方法来做基准测试,比如10次。 内部方法根据需要进行大量的迭代,比如10,000或更多,以使其运行时间上升至至少数十毫秒。 我甚至不打扰nanoTime
因为如果微秒精度对你很重要,那只是测量太短时间间隔的标志。
当你这样做时,你可以很容易地让JIT在代替解释版本后执行内部方法的编译版本。 另一个好处是你可以确保内部方法的时间稳定。
如果你想为一个简单的函数做一个真正的基准,你应该使用一个微型基准测试工具,比如Caliper。 试图制定自己的基准将会简单得多。
链接地址: http://www.djcxy.com/p/76371.html上一篇: Performance test independent of the number of iterations