Saturday, 15 May 2010

java - Strange method invocation optimization issue -



java - Strange method invocation optimization issue -

i have been testing problem slow datainputstream.readbyte() method working, , found interesting, incomprehensible issue. i'm using jdk1.7.0_40, windows 7 64 bit.

consider have huge byte-array , reading info it. , let's compare 4 methods reading byte-by-byte array:

reading via simple loop reading via bytearrayinputstream -> datainputstream reading via bytearrayinputstream -> our own datainputstream implementation (mydatainputstream) reading via bytearrayinputstream , re-create of method readbyte() datainputstream.

i have found next results (after long-time of test-loop iterating):

loop took aprox. 312446094 ns datainputstream took apox. 2555898090 ns mydatainputstream took aprox. 2630664298 ns via method readbyte() re-create took 309265568 ns

in other words, we have unusual optimization issue: same operations via object method invocation take in 10 times longer work, via "native" implementation.

the question: why?.

for information:

@test public void testbytes1() throws ioexception { byte[] bytes = new byte[1_000_000_000]; random r = new random(); (int = 0; < bytes.length; i++) bytes[i] = (byte) r.nextint(); { system.out.println(); bytes[r.nextint(1_000_000_000)] = (byte) r.nextint(); testloop(bytes); testdis(bytes); testmydis(bytes); testviamethod(bytes); } while (true); } private void testdis(byte[] bytes) throws ioexception { long time1 = system.nanotime(); long c = 0; seek (bytearrayinputstream bais = new bytearrayinputstream(bytes); datainputstream dis = new datainputstream(bais)) { (int = 0; < bytes.length; i++) { c += dis.readbyte(); } } long time2 = system.nanotime(); system.out.println("dis: \t\t\t\t" + (time2 - time1) + "\t\t\t\t" + c); } private void testmydis(byte[] bytes) throws ioexception { long time1 = system.nanotime(); long c = 0; seek (bytearrayinputstream bais = new bytearrayinputstream(bytes); mydatainputstream dis = new mydatainputstream(bais)) { (int = 0; < bytes.length; i++) { c += dis.readbyte(); } } long time2 = system.nanotime(); system.out.println("my dis: \t\t\t" + (time2 - time1) + "\t\t\t\t" + c); } private void testviamethod(byte[] bytes) throws ioexception { long time1 = system.nanotime(); long c = 0; seek (bytearrayinputstream bais = new bytearrayinputstream(bytes) ) { (int = 0; < bytes.length; i++) { c += readbyte(bais); } } long time2 = system.nanotime(); system.out.println("via method: \t\t" + (time2 - time1) + "\t\t\t\t" + c); } private void testloop(byte[] bytes) { long time1 = system.nanotime(); long c = 0; (int = 0; < bytes.length; i++) { c += bytes[i]; } long time2 = system.nanotime(); system.out.println("loop: \t\t\t\t" + (time2 - time1) + "\t\t\t\t" + c); } public final byte readbyte(inputstream in) throws ioexception { int ch = in.read(); if (ch < 0) throw new eofexception(); homecoming (byte)(ch); } static class mydatainputstream implements closeable { inputstream in; mydatainputstream(inputstream in) { this.in = in; } public final byte readbyte() throws ioexception { int ch = in.read(); if (ch < 0) throw new eofexception(); homecoming (byte)(ch); } @override public void close() throws ioexception { in.close(); } }

p.s. update thoose, in uncertainty results, printout, using -xx:+printcompilation -verbose:gc -xx:cicompilercount=1

37 1 java.lang.string::hashcode (55 bytes) 41 2 java.lang.string::charat (29 bytes) 43 3 java.lang.string::indexof (70 bytes) 49 4 java.lang.abstractstringbuilder::ensurecapacityinternal (16 bytes) 52 5 java.lang.abstractstringbuilder::append (29 bytes) 237 6 java.util.random::nextint (7 bytes) 237 9 n sun.misc.unsafe::compareandswaplong (native) 238 7 java.util.concurrent.atomic.atomiclong::get (5 bytes) 238 8 java.util.concurrent.atomic.atomiclong::compareandset (13 bytes) 239 10 java.util.random::next (47 bytes) 239 11 % fias.testarrays::testbytes1 @ 15 (77 bytes) 9645 11 % fias.testarrays::testbytes1 @ -2 (77 bytes) made not entrant 9646 12 % fias.testarrays::testloop @ 10 (77 bytes) 9964 12 % fias.testarrays::testloop @ -2 (77 bytes) made not entrant loop: 318726397 -500090432 9965 13 java.io.datainputstream::readbyte (23 bytes) 9966 14 s java.io.bytearrayinputstream::read (36 bytes) 9967 15 % ! fias.testarrays::testdis @ 37 (279 bytes) dis: 2684374258 -500090432 12651 16 fias.testarrays$mydatainputstream::readbyte (23 bytes) 12652 17 % ! fias.testarrays::testmydis @ 37 (279 bytes) dis: 2675570541 -500090432 15327 18 fias.testarrays::readbyte (20 bytes) 15328 19 % ! fias.testarrays::testviamethod @ 23 (179 bytes) via method: 2367507141 -500090432 17694 20 fias.testarrays::testloop (77 bytes) 17699 21 % fias.testarrays::testloop @ 10 (77 bytes) loop: 374525891 -500090567 18069 22 ! fias.testarrays::testdis (279 bytes) dis: 2674626125 -500090567 20745 23 ! fias.testarrays::testmydis (279 bytes) dis: 2671418683 -500090567 23417 24 ! fias.testarrays::testviamethod (179 bytes) via method: 2359181776 -500090567 loop: 315081855 -500090663 dis: 2558738649 -500090663 dis: 2627056034 -500090663 via method: 311692727 -500090663 loop: 317813286 -500090778 dis: 2565161726 -500090778 dis: 2630665760 -500090778 via method: 314594434 -500090778 loop: 313695660 -500090797 dis: 2568251556 -500090797 dis: 2635236578 -500090797 via method: 311882312 -500090797 loop: 316781686 -500090929 dis: 2563535623 -500090929 dis: 2638487613 -500090929 via method: 313170789 -500090929

upd-2: here benchmark , results kindly given @maaartinus.

surprisingly, reason try-with-resources statement on mydatainputstream/datainputstream

if move initialization within seek block performance loop/method invocation

private void testmydis(byte[] bytes) throws ioexception { final long time1 = system.nanotime(); long c = 0; seek (bytearrayinputstream bais = new bytearrayinputstream(bytes)) { final mydatainputstream dis = new mydatainputstream(bais); (int = 0; < bytes.length; i++) { c += dis.readbyte(); } } final long time2 = system.nanotime(); system.out.println("my dis: \t\t\t" + (time2 - time1) + "\t\t\t\t" + c); }

i think unnecessary resource jit cannot utilize range check elimination

java performance optimization

No comments:

Post a Comment