Tuesday, 15 January 2013

java - Why does test1() run much faster than test2()? -



java - Why does test1() run much faster than test2()? -

import java.util.random; public class test{ static int r = new random().nextint(2); static int a(){ homecoming r==1 ? 1 :0; } public static void test1() throws exception { // system.out.println(1403187139018l); (int = 0; < 1073741824; i++) {}//* // thread.sleep(20000); long d = 0; (int j = 0; j < 10; j++) { long y = system.currenttimemillis(); (int x = 0; x < 1073741823; x++) { d += r==0?1:0; } system.out.println((system.currenttimemillis() -y)); } } public static void test2() throws exception{ // thread.sleep(20000); long d = 0; (int j = 0; j < 10; j++) { long y = system.currenttimemillis(); (int x = 0; x < 1073741824; x++) { d += r==0?1:0; } system.out.println((system.currenttimemillis() -y)); // system.out.println("time:"+ (system.currenttimemillis() - y)); } } public static void main(string[] args) throws exception{ // thread.sleep(20000); test1(); test2(); } }

when run above code, output:

32 26 28 28 32 29 35 33 30 31 1321 1308 1324 1277 1348 1321 1337 1413 1287 1331

why test1 much faster ?

there no difference except followings:

system.out.println(1403187139018l); (int = 0; < 1073741824; i++) {}//*

also, time cost test1 25-35 milliseconds, find unbelievable. wrote same code in c , needed 4 seconds run every loop.

this behavior seems strange. how know when add:

system.out.println(1403187139018l); (int = 0; < 1073741824; i++) {}//*

also, if alter

r==0?1:0

to

a()

then test2() runs faster test1().

the output is:

1403187139018 3726 3729 3619 3602 3797 4362 4498 3816 4143 4368 1673 1386 1388 1323 1296 1337 1294 1283 1235 1460

the original legacy code: ...

long t = system.currenttimemillis(); mappedbytebuffer mbb = map(new file("temp.mmp"), 1024l * 1024 * 1024); system.out.println("load " + (system.currenttimemillis() - t));//* (int = 0; < 2014l * 1024 * 1024; i++) {}//* int d = 0; (int j = 0; j < 10; j++) { t = system.currenttimemillis(); mbb.position(0); mbb.limit(mbb.capacity()); (int = 0; < mbb.capacity(); i++) { d += mbb.get(); } .... } system.out.println(d);

there many factors impact jit compilations:

execution statistics. while interpreter runs method collects different statistics: paths executed, branches taken, class instances seen etc. in test1 statistics collected within first (empty) loop , fools jit compiler real execution scenario. class initialization , uncommon traps. when remove first system.out.println test1, not classes related printing initialized. effort invoke method of uninitialized class causes uncommon trap leads deoptimization , farther recompilation of method using new knowledge. the wrong statistics collected in test1 plays bad joke when replace r==0?1:0 a(). in compiled test1 method a() has never been executed before , has not had chance optimized. that's why works slower test2 has been compiled knowledge of a().

of course, hard predict factors affecting jit-compilation when trying write microbenchmark scratch. that's why recommended way benchmark code using special frameworks of these problems have been solved already. suggest jmh.

java performance profile

No comments:

Post a Comment