Meh*_*dad 6 c++ compiler-construction performance exception-handling visual-c++
我有一个数千行的项目,有一个巨大的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;
}
Run Code Online (Sandbox Code Playgroud)
但是,当我简单地将其更改为
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;
}
Run Code Online (Sandbox Code Playgroud)
编译时间减少到2.48秒!
我可以告诉罪魁祸首是异常处理代码,因为当我删除周围的try
/时catch
,我得到相同的编译时间减少.
此外,如果我将run
函数标记为__forceinline
,则编译时间增加到 10.02!但是如果我在拿出try
/ 之后这样做catch
,那么它会下降到仅仅3.27秒.
但是给出了什么?当代码直接位于try
块体内时,编译器究竟需要做什么才会变得更加计算密集?
笔记:
/O2 /Gm- /GS /EHsc
删除/EHsc
也加快了编译速度)我怀疑差异与额外的清理代码有关。函数中声明的 C++ 对象在离开函数时就会被销毁,因此它们的销毁代码已经在函数尾声中,并且(我认为)堆栈展开(异常处理过程的一部分)可以利用该代码。如果您需要在不离开函数的情况下销毁所有这些对象,则需要生成和管理额外的销毁代码,这可能会影响构建时间和二进制大小。你能说二进制大小是否有差异吗?
尽管坦率地说,我很惊讶影响(时间/大小)是可以衡量的。“800 行”在 C++ 对象创建方面是否异常丰富?(也许是间接的)