同一函数中的异常处理会使编译时间减慢 2 倍以上,为啥?
Posted
技术标签:
【中文标题】同一函数中的异常处理会使编译时间减慢 2 倍以上,为啥?【英文标题】:Exception handling in the same function slows compile times by > 2x, why?同一函数中的异常处理会使编译时间减慢 2 倍以上,为什么? 【发布时间】:2014-07-21 00:24:14 【问题描述】:我有一个数千行的项目,其中包含一个巨大的 main
(约 800 行)。
包含 main 函数的文件编译需要 7.94 秒。
代码结构如下:
int main(int argc, char *argv[])
int result = 0;
try
/* 800 lines of code here */
catch (std::invalid_argument const &ex)
std::cerr << ex.what() << std::endl;
return EINVAL;
catch (std::runtime_error const &ex)
std::cerr << ex.what() << std::endl;
return -1;
return 0;
但是,当我将其更改为
void run(int argc, char *argv[])
/* 800 lines of code here */
int main(int argc, char *argv[])
int result = 0;
try
run(argc, argv);
catch (std::invalid_argument const &ex)
std::cerr << ex.what() << std::endl;
return EINVAL;
catch (std::runtime_error const &ex)
std::cerr << ex.what() << std::endl;
return -1;
return 0;
编译时间减少到 2.48 秒!
我可以说罪魁祸首是异常处理代码,因为当我删除周围的 try
/catch
时,我得到了同样的编译时间减少。
此外,如果我将run
函数标记为__forceinline
,编译时间增加到10.02!但是如果我在取出try
/catch
之后再这样做,那么它会下降到仅仅 3.27 秒。
但是什么给了?当代码直接位于 try
块的主体内时,编译器究竟需要做什么才能使计算量变得如此之多?
注意事项:
我正在 RELEASE 模式下编译 Microsoft Visual C++ Nov 2013 CTP 编译器(原生 x64) 相关编译器选项:/O2 /Gm- /GS /EHsc
(删除 /EHsc
也可以加快编译速度)
【问题讨论】:
我认为除了编译器设计者之外没有人可以回答为什么这个问题。编译器可能非常复杂,并且很容易从看似不相关的设计决策中触发意想不到的后果。编译器的主要工作是正确;性能是次要考虑因素。请注意,我并不是说在这种情况下确保正确性需要额外的时间。我不知道它在做什么,而且微软编译器团队之外的其他人也不太可能这样做。 你试过其他编译器吗? 我对 try/catch 的开销并不感到惊讶,但让我感到惊讶的是,这两个代码之间的性能差异! @Samer:不,我没有尝试在其他编译器上测量时间。如果我得到更多数据,我会发布更新。 @GregHewgill:我希望也许有更多编译器经验的人可以做出有根据的猜测。 【参考方案1】:我怀疑差异与额外的清理代码有关。在函数中声明的 C++ 对象在离开时会被销毁,因此它们的销毁代码已经在函数结尾处,并且(我认为)堆栈展开(异常处理过程的一部分)可以使用该代码。如果您需要在离开函数的情况下销毁所有这些对象 - 需要生成和管理额外的销毁代码,这会影响构建时间和二进制大小。你能说二进制大小是否有差异吗?
尽管坦率地说,我很惊讶这两种影响(时间/大小)都是可测量的。 “800 行”在 C++ 对象创建方面是否异常丰富? (也许是间接的)
【讨论】:
以上是关于同一函数中的异常处理会使编译时间减慢 2 倍以上,为啥?的主要内容,如果未能解决你的问题,请参考以下文章