java VS C++
dwing吧
全部回复
仅看楼主
level 13
dwing 楼主
我用C++和java分别写出几乎完全相同的素数计算程序,运行结果令人诧异:C++ (VC6.0)速度优化编译运行:1.234sjava(SDK1.42)编译字节码运行:1.390s难道程序过于简单不能说明问题,还是java确实没有想象中效率那么差?// C++ 程序#include
int searchprime(int num,int *out){ int pn=0; bool *mask=new bool[num+1]; for(int i=2;i<=num;i++) if(!mask[i]) { out[pn++]=i; if(i<32767) for(int j=i*i;j<=num;j+=i) mask[j]=true; } delete []mask; return pn;}void main(){ int *out=new int[664579]; printf("搜索1 ~ 10000000......"); int num=searchprime(10000000,out); printf("找到%d个素数,最后一个素数是%d.\n",num,out[num-1]); delete []out;}// java 程序public class prime{ static int searchprime(int num,int out[]) { int pn=0; boolean mask[]=new boolean[num+1]; for(int i=2;i<=num;i++) if(!mask[i]) { out[pn++]=i; if(i<32767) for(int j=i*i;j<=num;j+=i) mask[j]=true; } return pn; } public static void main(String args[]) { int out[]=new int[664579]; System.out.print("搜索1 ~ 10000000......"); int num=searchprime(10000000,out); System.out.println("找到"+num+"个素数,最后一个素数是"+out[num-1]+"."); }}
2006年06月30日 02点06分 1
level 13
dwing 楼主
不用怀疑VC的编译质量,反汇编可以发现与直接用汇编写的程序速度几乎没有差别:00401000 /$ 56 push esi00401001 |. 8B7424 08 mov esi,[esp+8]00401005 |. 57 push edi00401006 |. 8D46 01 lea eax,[esi+1]00401009 |. 50 push eax0040100A |. 33FF xor edi,edi0040100C |. E8 A5000000 call
00401011 |. BA 02000000 mov edx,200401016 |. 83C4 04 add esp,400401019 |. 3BF2 cmp esi,edx0040101B |. 7C 33 jl short 004010500040101D |. 53 push ebx0040101E |. 8B5C24 14 mov ebx,[esp+14]00401022 |> 803C02 00 /cmp byte ptr [edx+eax],000401026 |. 75 22 |jnz short 0040104A00401028 |. 8914BB |mov [ebx+edi*4],edx0040102B |. 47 |inc edi0040102C |. 81FA FF7F0000 |cmp edx,7FFF00401032 |. 7D 16 |jge short 0040104A00401034 |. 8BCA |mov ecx,edx00401036 |. 0FAFCA |imul ecx,edx00401039 |. 3BCE |cmp ecx,esi0040103B |. 7F 0D |jg short 0040104A0040103D |. 8D49 00 |lea ecx,[ecx]00401040 |> C60401 01 |/mov byte ptr [ecx+eax],100401044 |. 03CA ||add ecx,edx00401046 |. 3BCE ||cmp ecx,esi00401048 |.^ 7E F6 |\jle short 004010400040104A |> 42 |inc edx0040104B |. 3BD6 |cmp edx,esi0040104D |.^ 7E D3 \jle short 004010220040104F |. 5B pop ebx00401050 |> 50 push eax00401051 |. E8 5A000000 call
00401056 |. 83C4 04 add esp,400401059 |. 8BC7 mov eax,edi0040105B |. 5F pop edi0040105C |. 5E pop esi0040105D \. C3 retn
2006年06月30日 02点06分 2
level 13
dwing 楼主
也不用考虑系统调用(printf,delete,print,println)所用的时间,去掉这些运行时间没有可察觉的变化.
2006年06月30日 02点06分 3
level 13
dwing 楼主
楼上的回复不是在搞笑吧-_-感到奇怪的是java为什么这么快......
2006年06月30日 05点06分 5
level 13
dwing 楼主
因为VC已经优化的和汇编差不多了,所以怀疑javaSDK解释器把比较短的代码做了预处理,执行循环内部就不用调用解释器,直接执行已经解释的机器码,所以速度差不多,不过这只是猜测,也许测试大一些的程序才能说明问题.java比C++快的说法我以前就听说了,CSDN上也吵的很厉害.其实java只是种语言,不代表一种编译器,执行时先把字节码直接优化转换成机器码,速度确实比一边解释一边执行要快,但也不能比说比C++快,因为C++也是一种语言,不是编译器.主流的C++/java编译器效率如何,有足够证明的实验结果时再说.
2006年07月01日 01点07分 12
level 13
dwing 楼主
1楼的测试结果是在P4 2.5GHz CPU上测试的结果.我又在Athlon1600+上测试了一下(比2.5GHz的P4还快,呵呵):C++ (VC6.0)速度优化编译运行:1.081sjava(SDK1.42)编译字节码运行:1.271s其中java命令是否使用-server参数,运行此程序速度没有任何影响.结论是java(SDK)不像想象中那么慢,但还是速度不能与C++(VC)相比.如果谁能证明"java比C++"快,请提供java的测试源码.
2006年07月01日 02点07分 13
level 13
dwing 楼主
也不能说java像C/C++一样变成编译类语言,而是还有中间字节码的概念,否则就和设计的初衷背道而驰了.然而,字节码是解释执行的还是编译后再执行差别就很大了,估计像1楼那样小的程序,javaSDK直接编译了再执行的,所以速度与C++编译的程序差不多.
2006年07月01日 08点07分 16
level 13
dwing 楼主
我用OD跟踪了java的程序,结果不出所料,果然把那个函数完全编译了再运行的,下面这些就是java版searchprime函数的编译后代码,质量比C++编译的差太多,不过运行速度仅慢了1/5还算可以.00B65B90 push  ebp00B65B91 mov   ebp,esp00B65B93 mov   [esp-3000],eax00B65B9A sub   esp,2000B65B9D mov   dword ptr [ebp-4],000B65BA4 mov   esi,[ebp+C]00B65BA7 inc   esi00B65BA8 mov   edx,1401029000B65BAD cmp   esi,0FFFFFF00B65BB3 ja   00B65D4100B65BB9 mov   eax,[A49618]00B65BBF lea   edi,[eax+esi]00B65BC2 add   edi,1300B65BC5 and   edi,FFFFFFF800B65BC8 cmp   edi,eax00B65BCA jb   00B65D4100B65BD0 cmp   edi,[A495F0]00B65BD6 ja   00B65D4100B65BDC cmpxchg [A49618],edi00B65BE3^ jnz   00B65BB900B65BE9 mov   dword ptr [eax],100B65BEF mov   [eax+4],edx00B65BF2 mov   [eax+8],esi00B65BF5 sub   edi,eax00B65BF7 sub   edi,0C00B65BFA je   00B65C2400B65C00 xor   esi,esi00B65C02 shr   edi,300B65C05 jnb   00B65C1500B65C0B mov   [eax+edi*8+C],esi00B65C0F je   00B65C2400B65C15 mov   [eax+edi*8+8],esi00B65C19 mov   [eax+edi*8+4],esi00B65C1D dec   edi00B65C1E^ jnz   00B65C1500B65C24 mov   [ebp-8],eax00B65C27 mov   dword ptr [ebp-C],200B65C2E mov   esi,[ebp-C]00B65C31 cmp   esi,[ebp+C]00B65C34 jg   00B65CE500B65C3A mov   esi,[ebp-8]00B65C3D mov   edi,[ebp-C]00B65C40 cmp   edi,[esi+8]00B65C43 jnb   00B65D5600B65C49 movsx  ebx,byte ptr [esi+edi+C]00B65C4E cmp   ebx,000B65C51 jnz   00B65CD900B65C57 mov   esi,[ebp+8]00B65C5A mov   ebx,[ebp-4]00B65C5D mov   edi,ebx00B65C5F inc   ebx00B65C60 mov   [ebp-4],ebx00B65C63 mov   ebx,[ebp-C]00B65C66 cmp   edi,[esi+8]00B65C69 jnb   00B65D5D00B65C6F mov   [esi+edi*4+C],ebx00B65C73 cmp   ebx,7FFF00B65C79 jge   00B65CD900B65C7F mov   edi,[ebp-C]00B65C82 imul  edi,edi00B65C85 mov   esi,edi00B65C87 mov   [ebp-10],esi00B65C8A mov   ebx,[ebp+C]00B65C8D mov   eax,[ebp-8]00B65C90 mov   edx,[ebp-C]00B65C93 mov   ecx,[ebp-10]00B65C96 jmp   00B65CA700B65C9B mov   ebx,[ebp+C]00B65C9E mov   eax,[ebp-8]00B65CA1 mov   edx,[ebp-C]00B65CA4 mov   ecx,[ebp-10]00B65CA7 cmp   ecx,ebx00B65CA9 jle   00B65CC000B65CAF mov   [ebp+C],ebx00B65CB2 mov   [ebp-8],eax00B65CB5 mov   [ebp-C],edx00B65CB8 mov   [ebp-10],ecx00B65CBB jmp   00B65CD900B65CC0 mov   esi,ecx00B65CC2 cmp   ecx,[eax+8]00B65CC5 jnb   00B65D6400B65CCB mov   byte ptr [eax+esi+C],100B65CD0 add   esi,edx00B65CD2 mov   ecx,esi00B65CD4^ jmp   00B65CA700B65CD9 mov   esi,[ebp-C]00B65CDC inc   esi00B65CDD mov   [ebp-C],esi00B65CE0^ jmp   00B65C2E00B65CE5 mov   eax,[ebp-4]00B65CE8 mov   esp,ebp00B65CEA pop   ebp00B65CEB retn
2006年07月01日 08点07分 17
level 13
dwing 楼主
2楼贴的代码比较乱,我重新整齐地贴一遍C++(VC6)编译searchprime函数的代码,各位可以对比一下java(SDK1.42)编译器和C++(VC6)编译器生成代码的质量,执行速度之谜随之解开...00401000 /$>push  esi00401001 |.>mov   esi,[esp+8]00401005 |.>push  edi00401006 |.>lea   eax,[esi+1]00401009 |.>push  eax0040100A |.>xor   edi,edi0040100C |.>call  
00401011 |.>mov   edx,200401016 |.>add   esp,400401019 |.>cmp   esi,edx0040101B |.>jl   short 004010500040101D |.>push  ebx0040101E |.>mov   ebx,[esp+14]00401022 |>>/cmp   byte ptr [edx+eax],000401026 |.>|jnz   short 0040104A00401028 |.>|mov   [ebx+edi*4],edx0040102B |.>|inc   edi0040102C |.>|cmp   edx,7FFF00401032 |.>|jge   short 0040104A00401034 |.>|mov   ecx,edx00401036 |.>|imul  ecx,edx00401039 |.>|cmp   ecx,esi0040103B |.>|jg   short 0040104A0040103D |.>|lea   ecx,[ecx]00401040 |>>|/mov   byte ptr [ecx+eax],100401044 |.>||add   ecx,edx00401046 |.>||cmp   ecx,esi00401048 |.>|\jle   short 004010400040104A |>>|inc   edx0040104B |.>|cmp   edx,esi0040104D |.>\jle   short 004010220040104F |.>pop   ebx00401050 |>>push  eax00401051 |.>call  
00401056 |.>add   esp,400401059 |.>mov   eax,edi0040105B |.>pop   edi0040105C |.>pop   esi0040105D \.>retn再看一下其中的核心循环(占90%以上运行时间):C++(VC6)版:00401040 mov   byte ptr [ecx+eax],100401044 add   ecx,edx00401046 cmp   ecx,esi00401048 jle   short 00401040java(SDK1.42)版:00B65CA7 cmp   ecx,ebx00B65CA9 jle   00B65CC000B65CAF mov   [ebp+C],ebx00B65CB2 mov   [ebp-8],eax00B65CB5 mov   [ebp-C],edx00B65CB8 mov   [ebp-10],ecx00B65CBB jmp   00B65CD900B65CC0 mov   esi,ecx00B65CC2 cmp   ecx,[eax+8]00B65CC5 jnb   00B65D6400B65CCB mov   byte ptr [eax+esi+C],100B65CD0 add   esi,edx00B65CD2 mov   ecx,esi00B65CD4^ jmp   00B65CA7java是从源代码编译成字节码,运行时又把字节码转换成本地机器码,两遍转换确实可能造成编译质量变差,就像CD上的一首歌转换成MP3,再把128kMP3转换成64kWMA,这样转换肯定不如直接把CD上的歌直接转换成64kWMA.
2006年07月01日 08点07分 18
level 13
dwing 楼主
字节码应该与机器码更近,可以说是一种虚拟CPU指令集.
2006年07月01日 12点07分 20
level 13
dwing 楼主
我说过了用OD跟踪的.不过对于java字节码我还没有深入了解.
2006年07月04日 11点07分 22
level 13
dwing 楼主
测试的电脑不是超线程的,而且根据反汇编的代码看也不是多线程的.
2006年07月10日 02点07分 24
level 13
dwing 楼主
java程序和C++程序不可能合并到一起连续运行的.另外,上面速度测试结果是执行3遍以上得到的稳定的平均值.
2006年07月10日 04点07分 26
level 13
dwing 楼主
其实即使是300M的CPU已经是很快的了,大多数应用都没有这么高的计算量,很多是图像方面软渲染导致性能不足,只要有专用的图像硬件加速就会有很大帮助,想想过去FC游戏机的CPU性能是低到什么程度.
2011年04月21日 01点04分 31
1