このチケットに答えようとしています: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.);
}
それは私に与えました:
- A.class.isAssignableFrom(b.getClass()): 100000回の反復に15ミリ秒かかりました
- A.class.isInstance (b):100000回の反復に12ミリ秒かかりました
- b instanceof A:100000回の反復に6ミリ秒かかりました
しかし、反復回数を試してみると、パフォーマンスは一定であることがわかります。Integer.MAX_VALUEの場合:
- A.class.isAssignableFrom(b.getClass()): 2147483647の反復には15ミリ秒かかりました
- A.class.isInstance (b):2147483647の反復には12ミリ秒かかりました
- b instanceof A:2147483647の反復には6ミリ秒かかりました
それがコンパイラの最適化だと思って(私はこのテストを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);
}
ただし、パフォーマンスは反復回数に「依存しません」。誰かがその行動を説明できますか?