关于异常处理所谓C++处理效率比DMD高的原因
DavidL
2007-09-10
DMD版:
PUSH EBP MOV EBP,ESP PUSH -1 MOV EDX,DWORD PTR FS:[0] PUSH mytest.004020F1 PUSH EDX MOV DWORD PTR FS:[0],ESP SUB ESP,8 SUB ESP,10 PUSH EBX PUSH ESI PUSH EDI MOV DWORD PTR SS:[EBP-24],EAX XOR ECX,ECX MOV DWORD PTR SS:[EBP-20],ECX CMP DWORD PTR SS:[EBP+C],ECX JLE L034 L017: INC DWORD PTR DS:[41F6D0] XOR EAX,EAX MOV DWORD PTR DS:[41F6D4],EAX MOV DWORD PTR SS:[EBP-1C],EAX CMP EAX,DWORD PTR SS:[EBP+8] JGE L030 L023: MOV DWORD PTR SS:[EBP-4],0 CALL DWORD PTR SS:[EBP-24] MOV DWORD PTR SS:[EBP-4],-1 INC DWORD PTR SS:[EBP-1C] MOV EDX,DWORD PTR SS:[EBP-1C] CMP EDX,DWORD PTR SS:[EBP+8] JL L023 L030: INC DWORD PTR SS:[EBP-20] MOV EBX,DWORD PTR SS:[EBP-20] CMP EBX,DWORD PTR SS:[EBP+C] JL L017 L034: PUSH DWORD PTR DS:[41F6D4] MOV ESI,mytest.00417120 PUSH ESI PUSH DWORD PTR DS:[41709C] PUSH DWORD PTR DS:[417098] MOV ECX,mytest.00417110 PUSH ECX PUSH DWORD PTR DS:[41F6D0] PUSH ESI PUSH DWORD PTR DS:[41708C] PUSH DWORD PTR DS:[417088] PUSH ECX PUSH DWORD PTR DS:[41F6E0] CALL mytest.00402208 ADD ESP,10 PUSH EAX CALL mytest.00402208 ADD ESP,0C PUSH EAX CALL mytest.00402208 ADD ESP,10 PUSH EAX CALL mytest.00402208 ADD ESP,0C MOV ECX,DWORD PTR SS:[EBP-C] MOV DWORD PTR FS:[0],ECX POP EDI POP ESI POP EBX MOV ESP,EBP POP EBP RETN 8 VS2005 C++版 PUSH ESI MOV ESI,320 MOV ECX,1 XOR EDX,EDX LEA ECX,DWORD PTR DS:[ECX] L005: ADD DWORD PTR DS:[40337C],ECX MOV DWORD PTR DS:[403374],EDX MOV EAX,100000 L008: ADD DWORD PTR DS:[403374],ECX SUB EAX,ECX JNZ L008 SUB ESI,ECX JNZ L005 MOV EAX,DWORD PTR DS:[403374] MOV ECX,DWORD PTR DS:[40337C] PUSH EAX PUSH ECX PUSH k.004020F4 CALL printf ADD ESP,0C POP ESI RETN 我的外循环数改成了8*100=0x320(VS2005的代码里面直接写到了函数里面去了) 至于异常处理纯粹是最外层的一个安装,根本对效率不产生影响,影响效率的是循环的代码实现 关键在于VS2005的/ltcg项 Link Time Code Generation,它把代码的参数相当于DMD的模板实例化了,DMD的代码每次循环都从堆栈里拿参数也略显笨拙,不是最好的实现。 这种问题应该多调查,没看到代码生成不要随便猜测,不要随便下结论,否则会误导别人。 |
|
redsea
2007-09-10
这些汇编代码我看不懂那里是安装异常框架, 哪里是调用函数指针. 如果是 VS 2005 集成环境显示反汇编代码, 还有源码对应的时候, 还好懂点.
我就当内部实现是一个黑盒,两份代码, 一个是有 try, catch, 一个是没有, 其他代码都一样, 我管它内部代码怎么生成, 反正加上 try, catch 对我而言, 性能就是下降这么多. 即使是加上 try, 引起别的地方不能充分优化, 而不是异常处理本身的问题, 对我而言, 都是 try 带来的成本 (当然, 后者将来更有优化的可能.) |
|
oldrev
2007-09-10
一看汇编就头疼
异常其实只要别用的太细就应该对性能没大的影响 |
|
DavidL
2007-09-10
分析了有try和没try的两种DMD生成的代码,结论是有try的情形的时候DMD的循环对比是和堆栈里面的值进行对比的,没有try的时候就优化为本地的寄存器了。
另外函数指针在MSVC里面是inline了,DMD里面的调用就没有。 |
|
DavidL
2007-09-10
好了,这个对比对于很多人来说测试可能根本就不公平!!!
因为C++的默认编译是/EHsc意思是只捕获代码写的C++类异常,如果/EHa捕获系统SEH那么代码和DMD一样慢。都要从堆栈里重新取值。 所以这种对比实际上一点意义都没有,当然作为自己兴趣研究以下到是没什么关系,只是这个性能测试和编译器一点关系都没有。 |