Does try-catch block decrease performance
此链接声明,
To catch exceptions we must place a portion of code under exception
inspection. This is done by enclosing that portion of code in a try
block. When an exceptional circumstance arises within that block, an
exception is thrown that transfers the control to the exception
handler. If no exception is thrown, the code continues normally and
all handlers are ignored.
这是否意味着在运行时,由于额外的"检查"任务,拥有一个try块会降低性能?
与错误代码处理相比,非异常路径上的异常通常更快。
好吧,显而易见的评论和什么相比?
与不处理错误相比,它明显降低了性能;但是性能是否值得缺乏正确性呢?我认为这不是,所以让我们假设您的意思是与用
在这种情况下,视情况而定。有多种机制用于实现异常。实际上,它们可以通过一种机制来实现,这种机制非常接近于
在C++中,所有主要编译器(GCC在4 .x Serie中引入它,MSVC使用它为64位代码)现在使用零成本异常模型。如果您阅读了需要4链接的技术论文,它将被列为表驱动方法。其思想是,对于程序中的每一个可能把寄存器丢到一个边表中的点,一些位和块将允许您找到正确的catch子句。老实说,与旧的策略相比,它的实现稍微复杂一些,但是零成本名称是由它是免费的这一事实派生出来的,不应该抛出任何异常。这与CPU上的分支预测失误形成对比。另一方面,当抛出异常时,由于表存储在一个寒冷的区域,所以惩罚是巨大的(所以很可能需要往返RAM或更糟的情况)。但是例外是例外,对吗?
总而言之,在现代C++编译器中,异常要比错误代码快,以较大的二进制文件为代价(由于静态表)。
为了精疲力竭,还有第三种选择:堕胎。不是通过状态或异常传播错误,而是可以中止进程。这只适用于有限数量的情况,但是它比任何一种选择都更好地优化。
查看C++性能技术报告草案第5.4部分这是关于C++中的catch catch语句开销的。
这一节有一点摘录:
5.4.1.1.2"代码"方法的时间开销
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ? On entry to each try-block ? Commit changes to variables enclosing the try-block ? Stack the execution context ? Stack the associated catch clauses ? On exit from each try-block ? Remove the associated catch clauses ? Remove the stacked execution context ? When calling regular functions ? If a function has an exception-specification, register it for checking ? As local and temporary objects are created ? Register each one with the current exception context as it is created ? On throw or re-throw ? Locate the corresponding catch clause (if any) – this involves some runtime check (possibly resembling RTTI checks) If found, then: destroy the registered local objects check the exception-specifications of the functions called in-between use the associated execution context of the catch clause Otherwise: call the terminate_handler6 |
它实际上取决于特定的编译器。
如果编译器倾向于考虑异常抛出一个真正的异常条件,那么您可以实现一个方案,在没有异常的情况下,开销为零,但反过来,如果出现异常和/或代码大小更大,则花费的时间将更多。
为了实现零开销的方法,您可以注意到,在C++中,您不能动态地改变代码,因此一旦知道堆栈帧和返回地址是什么,在解开或如果存在异常处理代码段时必须销毁的对象是什么。因此,引发异常的代码可以检查所有函数调用站点的全局表,以决定应该做什么。
另一方面,通过准备要显式销毁的对象列表以及在正常执行期间异常处理代码的地址,可以使异常抛出更快。这将使常规代码变慢,但异常处理更快,而且我会说代码更小。
不幸的是,C++中没有标准的方法完全放弃异常支持,所以必须对这种可能性付出一定的代价:标准库抛出异常,并且必须准备调用未知代码的任何代码(例如使用函数指针或调用虚拟方法)来处理异常。
这要看情况而定。对于异常处理,编译器必须做一些事情,否则它不能执行堆栈展开等操作。这意味着是的,异常处理会降低性能——即使没有抛出异常。多少-这取决于编译器的实现。
另一方面,你必须质疑自己:如果你自己插入错误处理代码,它真的会更快吗(测量它-不要猜测它)。它能和异常一样做吗(异常不能被客户机忽略-错误代码可以-并且它们可以进行堆栈展开,而错误代码不能)。此外,可以编写代码以便在例外情况下更易于维护。
简短:除非您的代码非常非常关键,否则请使用异常。即使你决定反对他们:首先测量。该规则有一个例外:在模块边界或析构函数中抛出异常是一个坏主意。
我建议在执行内存分配、删除、调用其他复杂函数等操作的函数中添加try catch。实际上,性能方面的try catch会增加一些开销。
但是考虑到捕获未知异常的好处,这是非常有帮助的。好的编程实践总是建议在代码中添加某种异常处理,除非您是一个异常的程序员。
我想知道为什么你这么关心小的性能问题,而不是整个程序都被一个异常所困扰。