关于异常处理所谓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一样慢。都要从堆栈里重新取值。

所以这种对比实际上一点意义都没有,当然作为自己兴趣研究以下到是没什么关系,只是这个性能测试和编译器一点关系都没有。



Global site tag (gtag.js) - Google Analytics