Итак, я хотел сравнить базовые функциональные возможности Java, чтобы добавить некоторые изменения в этот вопрос: Что такое выигрыш от объявления метода как статического.
Я знаю, что писать тесты иногда непросто, но что здесь происходит, я не могу объяснить.
Обратите внимание, что меня не интересует, как это исправить, но почему это происходит.
Класс Test:
public class TestPerformanceOfStaticVsDynamicCalls {
private static final long RUNS = 1_000_000_000L;
public static void main( String [] args ){
new TestPerformanceOfStaticVsDynamicCalls().run();
}
private void run(){
long r=0;
long start, end;
for( int loop = 0; loop<10; loop++ ){
// Benchmark
start = System.currentTimeMillis();
for( long i = 0; i < RUNS; i++ ) {
r += addStatic( 1, i );
}
end = System.currentTimeMillis();
System.out.println( "Static: " + ( end - start ) + " ms" );
start = System.currentTimeMillis();
for( long i = 0; i < RUNS; i++ ) {
r += addDynamic( 1, i );
}
end = System.currentTimeMillis();
System.out.println( "Dynamic: " + ( end - start ) + " ms" );
// Do something with r to keep compiler happy
System.out.println( r );
}
}
private long addDynamic( long a, long b ){
return a+b;
}
private static long addStatic( long a, long b ){
return a+b;
}
}
Я ожидал, что первый цикл будет прогреваться, а следующие циклы будут быстрее.
Запуск этого в Eclipse дал эти странные результаты:
Static: 621 ms
Dynamic: 631 ms
1000000001000000000
Static: 2257 ms
Dynamic: 2501 ms
2000000002000000000
Static: 2258 ms
Dynamic: 2469 ms
3000000003000000000
Static: 2231 ms
Dynamic: 2464 ms
4000000004000000000
Итак, wtf? Это стало медленнее. Для перекрестной проверки я запускаю тот же код с java/c 7:
Static: 620 ms
Dynamic: 627 ms
1000000001000000000
Static: 897 ms
Dynamic: 617 ms
2000000002000000000
Static: 901 ms
Dynamic: 615 ms
3000000003000000000
Static: 888 ms
Dynamic: 616 ms
4000000004000000000
Итак, здесь только статические вызовы стали медленнее для следующих циклов. Еще более странно, если я переделаю код только для печати r
после последнего цикла, который я получаю в Eclipse:
Static: 620 ms
Dynamic: 635 ms
Static: 2285 ms
Dynamic: 893 ms
Static: 2258 ms
Dynamic: 900 ms
Static: 2280 ms
Dynamic: 905 ms
4000000004000000000
И это с помощью java/c 7:
Static: 620 ms
Dynamic: 623 ms
Static: 890 ms
Dynamic: 614 ms
Static: 890 ms
Dynamic: 616 ms
Static: 886 ms
Dynamic: 614 ms
4000000004000000000
а при изменении порядка динамических/статических тестов в eclipse:
Dynamic: 618 ms
Static: 626 ms
1000000001000000000
Dynamic: 632 ms
Static: 2524 ms
2000000002000000000
Dynamic: 617 ms
Static: 2528 ms
3000000003000000000
Dynamic: 622 ms
Static: 2506 ms
4000000004000000000
и в java/c 7:
Dynamic: 625 ms
Static: 646 ms
1000000001000000000
Dynamic: 2470 ms
Static: 633 ms
2000000002000000000
Dynamic: 2459 ms
Static: 635 ms
3000000003000000000
Dynamic: 2464 ms
Static: 645 ms
4000000004000000000
Итак, что здесь происходит?
EDIT: Некоторые системные данные:
Java version "1.7.0_55"
OpenJDK Runtime Environment (IcedTea 2.4.7) (7u55-2.4.7-1ubuntu1)
OpenJDK 64-Bit Server VM (build 24.51-b03, mixed mode)
Intel(R) Core(TM) i7-2720QM CPU @ 2.20GHz
EDIT2:
Использование Java8:
Static: 620 ms
Dynamic: 624 ms
1000000001000000000
Static: 890 ms
Dynamic: 618 ms
2000000002000000000
Static: 891 ms
Dynamic: 616 ms
3000000003000000000
Static: 892 ms
Dynamic: 617 ms
4000000004000000000
Другие порядки кода дают похожие результаты (но ohter) здесь.