【问题标题】:Does try-catch block decrease performance [duplicate]try-catch 块是否会降低性能[重复]
【发布时间】:2013-05-22 23:37:53
【问题描述】:

link 声明,

要捕获异常,我们必须将一部分代码置于异常之下 检查。这是通过在 try 中包含该部分代码来完成的 堵塞。当该区块内出现异常情况时, 抛出异常,将控制权转移到异常 处理程序。如果没有抛出异常,则代码正常继续,并且 所有处理程序都被忽略。

这是否意味着由于运行时“检查”的额外任务,使用 try 块会降低性能?

【问题讨论】:

  • 通常是的,但除非它是一个时间紧迫的、被称为百万次、必须非常快的代码部分,否则我不会根据我的决定来决定是否对此使用例外。
  • (请注意,答案将取决于您使用的编译器,而不是 Java/C#/Python,其中异常处理只能以一种方式完成。)(但是,一个好的 try/catch 异常在没有抛出异常的情况下,开销几乎为 0 或 0。)
  • 这可能会回答你的问题:stackoverflow.com/questions/1897940/…
  • 相比什么?以其他方式处理异常情况(如果是,如何处理?)或者干脆不处理异常情况并希望它永远不会发生。

标签: c++ performance exception exception-handling try-catch


【解决方案1】:

TL;DR NO,与错误代码处理相比,异常通常在非异常路径上更快


嗯,显而易见的评论是与什么相比?

与不处理错误相比,它明显降低了性能;但是性能是否值得缺乏正确性?我认为它不是,所以让我们假设您的意思是与使用if 语句检查的错误代码相比。

在这种情况下,这取决于。有多种机制用于实现异常。实际上,它们可以使用与if 语句非常接近的机制来实现,最终它们的成本相同(或略高)。

尽管在 C++ 中,所有主要编译器(gcc 在 4.x 系列中引入它,MSVC 将它用于 64 位代码)现在都使用零成本异常模型。如果您阅读 Need4Sleep 链接到的 technical paper,它被列为表驱动方法。这个想法是,对于程序的每个点,可能会让您在边表中注册一些可以让您找到正确的 catch 子句的点点滴滴。老实说,它在实现方面比旧策略稍微复杂一些,但是 零成本 的名称源于它是 免费 的事实,应该不会抛出异常。将此与 CPU 上的分支错误预测进行对比。另一方面,当抛出异常时,惩罚是巨大的因为表存储在冷区(很可能需要往返 RAM 或更糟)...很特别,对吧?

总而言之,现代 C++ 编译器的异常比错误代码更快,但代价是更大的二进制文件(由于静态表)。


为了详尽无遗,还有第三种选择:堕胎。不是通过状态或异常传播错误,而是可以中止进程。这仅适用于有限数量的情况,但它比任何一种替代方案都优化得更好。

【讨论】:

    【解决方案2】:

    这真的取决于具体的编译器。

    如果编译器更愿意考虑抛出异常情况的异常,那么您可以实施一个方案,在没有异常的情况下,您的开销为零,但反过来,如果发生异常和/或将花费更多时间和/或更多的代码大小。

    要实现零开销方法,您会注意到在 C++ 中您不能动态更改代码,因此一旦您知道堆栈帧和返回地址是什么,就可以确定哪些对象在展开时必须被销毁,或者如果有一个异常处理代码部分。因此,引发异常的代码可以检查所有函数调用站点的全局表来决定应该做什么。

    另一方面,您可以通过准备要显式销毁的对象列表和正常执行期间异常处理代码的地址来加快异常抛出速度。这将使常规代码变慢,但异常处理更快,而且我会说代码更小。

    不幸的是,在 C++ 中没有标准的方法可以完全放弃异常支持,因此必须为这种可能性付出一些代价:标准库抛出异常和任何调用未知代码的代码(例如使用函数指针或调用虚方法)必须准备好处理异常。

    【讨论】:

      【解决方案3】:

      我建议在执行内存分配、删除、调用另一个复杂函数等的函数中添加 try catch。实际上,性能方面的 try catch 会增加一点开销。

      但考虑到捕获未知异常的优点,它非常有帮助。 除非您是出色的程序员,否则良好的编程习惯总是建议您在代码中添加某种异常处理。

      我想知道为什么您如此关注小的性能问题而不是整个程序卡在异常中。

      【讨论】:

        【解决方案4】:

        这取决于。对于异常处理,编译器必须做一些事情 - 否则它无法进行堆栈展开等。这意味着是的,异常处理会降低性能——即使没有抛出异常。多少 - 这取决于您的编译器实现。

        另一方面,您必须质疑自己:如果您自己插入错误处理代码,它真的会更快吗(测量它 - 不要猜测它)。它可以和异常做同样的事情吗(客户端不能忽略异常-错误代码可以-并且它们可以进行堆栈展开,而错误代码不能)。此外,代码可以编写得更易于维护,但有异常。

        简短:除非您的代码非常非常非常非常时间紧迫,否则请使用异常。即使您决定反对他们:首先衡量。规则的一个例外:跨模块边界或在析构函数中抛出异常是个坏主意。

        【讨论】:

          【解决方案5】:

          查看draft Technical Report on C++ Performance 的第 5.4 节 这特别是关于 c++ 中 try-catch 语句的开销。

          部分摘录:

          5.4.1.1.2 “代码”方法的时间开销

          • 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
          

          【讨论】:

          • 总结一下,这样当链接不可避免地死掉时,答案仍然有用。
          • @Patashu open-std 是一个控股网站,它的主要目标是保留这些链接。
          • 即使是好心的网站也可能倒闭。 SO 政策是没有链接的唯一答案。
          • -1 意图可能是好的,但是文档具体列出了2种方法(代码驱动和表驱动),不幸的是您列出了代码驱动的方法。 .. 目前仅由 MSVC 在 32 位模式下使用(在主要编译器中)。相反,表驱动方法更快(比if 语句)和fatter(尽管fat 被隔离在冷代码区域中)。我鼓励您阅读它,它的宠物名称是零成本异常模型。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-12-25
          • 1970-01-01
          • 2011-04-09
          • 1970-01-01
          • 1970-01-01
          • 2016-02-25
          • 1970-01-01
          相关资源
          最近更新 更多