Невдалий тест для Java
Декілька днів тому писав про дослідження швидкості виклику метода в мові php. І в кінці статті сказав, що цікаво було б подивитись на швидкодію всього цього щастя в інших мовах. І так як мені легше за все було створити аналогічний тест на java, то цим і зайнявся. Ну ось хочу поділитись результатами з Вами.
Замітка написана частково для того, щоб розвіяти міф про низьку швидкодію java, яким часто намагаються маніпулювати прихильники php (які на java жодного рядку програмного коду не писали і жодних замірів швидкодіє не проводили) і не тільки php в холіварах. Сподіваюсь, Вам буде цікаво.
Написанння тесту
Тест я вирішив для економії часу спростити. Оцінював лише час виконання без виклику методів, через виклик статичного метода звичайного метода, та метода, що звертається до статичних даних. Деякі тести для java написати не можливо (тут немає аналога $GLOBALS та функцій), а деякі повторювати було нецікаво
Взагалі, код аналогічний до тестів на php за виключенням того, що все описано в одному файлі.
public class MethodCall {
static int a = 0;
int b = 0;
static void a() {
a++;
}
void b() {
b++;
}
void c() {
a++;
}
public static void main(String [] args) {
int times = 20,
full = 0;
long beg, end;
for (int k = 0; k < times; k++) {
a = 0;
beg = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++)
MethodCall.a();
end = System.currentTimeMillis();
System.out.println("Static method call: "+(end-beg));
full += end-beg;
}
System.out.println("Average time: "+full*1./times+"(full: "+full+")");
full = 0;
MethodCall caller;
for (int k = 0; k < times; k++) {
caller = new MethodCall();
beg = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++)
caller.b();
end = System.currentTimeMillis();
System.out.println("Method call: "+(end-beg));
full += end-beg;
}
System.out.println("Average time: "+full*1./times+"(full: "+full+")");
caller = new MethodCall();
full = 0;
for (int k = 0; k < times; k++) {
a = 0;
beg = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++)
caller.c();
end = System.currentTimeMillis();
System.out.println("Method call (access to static): "+(end-beg));
full += end-beg;
}
System.out.println("Average time: "+full*1./times+"(full: "+full+")");
int j = 0;
full = 0;
for (int k = 0; k < times; k++) {
beg = System.currentTimeMillis();
j = 0;
for (int i = 0; i < 1000000; i++)
j++;
end = System.currentTimeMillis();
System.out.println("No method call: "+(end-beg));
full += end-beg;
}
System.out.println("Average time: "+full*1./times+"(full: "+full+")");
}
}
Написано все швидкоруч і буз жодного рефакторінга. Файтично весь програмний код - заміри та виведення даних. Ну просто таки жах :)
А тепер про результати
Це був цілковитий провал. На jvm від Sun виміряти час нормально мені не вдалось. Тому-що швидкість виконання занадто висока, щоб її поміряти: оскільки ця jvm використовує jit (just in time compiling), то всю суть програмного коду вона розкусила. Час виконання одного проходу коливався в межах 1-3 мілісекунди.
Оскільки система в той час щось там намагалась робити (все ж таки багатозадачність), то випадковим чином час виконання підіймався до 15-20 мілісекунд, що вбивало всю статистику. Отже я так нічого не наміряв.
Вирішив спробувати з gcj. Тут таки вдалось отримати результати, які можна оцінити і зробити на їх основі деякі висновки. Ось що я отримав:
1. Без виклику метода (122,35 мс).
2. Виклик статичного метода (866.9 мс).
3. Виклик метода, що працює зі статичними даними (887.7 мс).
4. Виклик метода (892.05 мс)
Висновки
Ну перший мій висновок: JIT в HotSpot від Sun працює (воно таки працює :)), та працює доволі ефективно. Так що порівняння швидкодії на коді, що добре оптимізується зі скриптовими мовами на зразок php сенсу немає.
Другий висновок: швидкість виконання програмного коду на java навіть не санівською машиною з JIT є вищою за швидкість виконання коду на php в середньому в півтора рази.
Висновок третій: в Java швидкість доступу до статичних методів і статичних даних є вищою, ніж швидкість доступу до звичайних методів. Тобто моя теорія, яку php розбив в java працює. І здається мені не тільки в java.
І як останнє слово, хотілось би сказати, що Java - потужна мова, що має високу швидкодію, значно вищу за швидкодію більшості скриптових мов. Так що використовувати її можна без жодних проблем, отримуючи насолоду від можливостей ООП та великої кількості готових бібліотек, в яких є практично будь-який функціонал.
Коментарі:
Що і треба було довести. Взагалі, ніколи не розумів людей, які порівнюють проект аматора для використання на своїй веб-сторінці (ПХП) із розробкою всесвітньовідомих учених, що створена спеціально для продакшена (Джава). До речі, Java швидша ніж PHP не у 2, а у десятки разів, і цьому є багато підтверджень.
Особисто для себе мені не треба було нічого доводити. Як я писав, мене цікавило більш за все, порівняння часу доступу до статичних та звичайних методів в java. І як побічний ефект і вказав на те, що швидкість роботи java значно вища за швидкість роботи скриптових мов і міф про низьку швидкодію цієї мови є лише міфом. Просто втомився на кожному кроці стикатись з такими помилковими твердженнями.



