RE:循环语句的写法、Client和Server的性能差异以及microbenchmark的不准确
这篇文章也是个回帖,继续用来偷懒发blog
=====================================================
一位朋友给了下面这段代码(在他给的代码中略作修改,避免了引入Random类、Integer装箱类导致不必要的因素),提出了2个问题:1.for (int i = 0, n = list.size(); i < n; i++)的写法是否会比for (int i = 0; i < list.size(); i++)更快?2.为何这段代码在Server VM下测出来的速度比Client VM还慢?
public class Client1 {public static void main(String[] args) {List<Object> list = new ArrayList<Object>();Object obj = new Object();// 填充数据for (int i = 0; i < 200000; i++) {list.add(obj);}long start;start = System.nanoTime();// 初始化时已经计算好条件for (int i = 0, n = list.size(); i < n; i++) {}System.out.println("判断条件中计算:" + (System.nanoTime() - start) + " ns");start = System.nanoTime();// 在判断条件中计算for (int i = 0; i < list.size(); i++) {}System.out.println("判断条件中计算:" + (System.nanoTime() - start) + " ns");}}
D:\_DevSpace\jdk1.7.0\fastdebug\bin>java -versionjava version "1.7.0-ea-fastdebug"Java(TM) SE Runtime Environment (build 1.7.0-ea-fastdebug-b127)Java HotSpot(TM) Client VM (build 20.0-b06-fastdebug, mixed mode)
0x01fcd554: inc %edx ; OopMap{[60]=Oop off=245} ;*if_icmplt ; - Client1::main@63 (line 17) 0x01fcd555: test %eax,0x1b0100 ; {poll} 0x01fcd55b: cmp %eax,%edx ;; 124 branch [LT] [B5] 0x01fcd55d: jl 0x01fcd554 ;*if_icmplt ; - Client1::main@63 (line 17)
0x01b6d610: inc %esi ;; block B7 [110, 118] 0x01b6d611: mov %esi,0x50(%esp) 0x01b6d615: mov 0x3c(%esp),%esi 0x01b6d619: mov %esi,%ecx ;*invokeinterface size ; - Client1::main@113 (line 23) 0x01b6d61b: mov %esi,0x3c(%esp) 0x01b6d61f: nop 0x01b6d620: nop 0x01b6d621: nop 0x01b6d622: mov $0xffffffff,%eax ; {oop(NULL)} 0x01b6d627: call 0x01b2b210 ; OopMap{[60]=Oop off=460} ;*invokeinterface size ; - Client1::main@113 (line 23) ; {virtual_call} 0x01b6d62c: nop ; OopMap{[60]=Oop off=461} ;*if_icmplt ; - Client1::main@118 (line 23) 0x01b6d62d: test %eax,0x160100 ; {poll} 0x01b6d633: mov 0x50(%esp),%esi 0x01b6d637: cmp %eax,%esi ;; 224 branch [LT] [B8] 0x01b6d639: jl 0x01b6d610 ;*if_icmplt ; - Client1::main@118 (line 23)
VM option '+PrintCompilation' 169 1 java.lang.String::hashCode (67 bytes) 172 2 java.lang.String::charAt (33 bytes) 174 3 java.lang.String::indexOf (87 bytes) 179 4 java.lang.Object::<init> (1 bytes) 185 5 java.util.ArrayList::add (29 bytes) 185 6 java.util.ArrayList::ensureCapacityInternal (26 bytes) 186 1% Client1::main @ 21 (79 bytes)
VM option '+PrintCompilation' 203 1 java.lang.String::charAt (33 bytes) 218 2 java.util.ArrayList::add (29 bytes) 218 3 java.util.ArrayList::ensureCapacityInternal (26 bytes) 221 1% Client1::main @ 21 (79 bytes) 230 1% made not entrant Client1::main @ -2 (79 bytes) 231 2% Client1::main @ 51 (79 bytes) 233 2% made not entrant Client1::main @ -2 (79 bytes) 233 3% Client1::main @ 65 (79 bytes)
0xc(%edi)
[edi + c]
[list + #offset_of_size_field]
list.sizeList<Object> list = flag ? new LinkedList<Object>() : new ArrayList<Object>();
0x0267df4c: inc %esi ;; block B10 [124, 132] 0x0267df4d: mov %esi,0x5c(%esp) 0x0267df51: mov 0x40(%esp),%eax 0x0267df55: mov %eax,%ecx ;*invokeinterface size ; - Client2::doTest@127 (line 24) 0x0267df57: mov %eax,0x40(%esp) 0x0267df5b: nop 0x0267df5c: nop 0x0267df5d: nop 0x0267df5e: mov $0xffffffff,%eax ; {oop(NULL)} 0x0267df63: call 0x0263b210 ; OopMap{[64]=Oop off=1080} ;*invokeinterface size ; - Client2::doTest@127 (line 24) ; {virtual_call} 0x0267df68: nop ; OopMap{[64]=Oop off=1081} ;*if_icmplt ; - Client2::doTest@132 (line 24) 0x0267df69: test %eax,0x200100 ; {poll} 0x0267df6f: mov 0x5c(%esp),%esi 0x0267df73: cmp %eax,%esi ;; 256 branch [LT] [B11] 0x0267df75: jl 0x0267df4c ;*if_icmplt