In Javascript, is it expensive to use try-catch blocks even if an exception is never thrown?
当没有任何异常被抛出时,使用多个try-catch块"慢"吗?我的问题和这个问题一样,但对于javascript。
假设我有20个函数,其中有try catch块。另一个函数调用这20个函数中的每一个。他们都不会抛出异常。由于这个try-catch块,我的代码执行速度会变慢还是执行得更差?
- stackoverflow.com/questions/12609527/…
- @蔡斯:但这不是说什么时候会发现例外吗?
- @Qantas94heavy-在jspef:jspef.com/search上有很多好的try/catch性能测试?Q =尝试/捕获。在大多数情况下,try是相当微不足道的,但这在一定程度上取决于您对slow的定义。如果你在寻找性能,那么有比try/catch更好的选择。@罗兰德很好地列出了一些不使用它们的好理由。
- @Chase Well 99%的JSPerf都被破坏了,而在其他时候,它们是误导性的,不能提供有用的信息。当然,一个几乎不做任何事情的函数在使用try-catch时只稍微慢一点。
- @伊莎莉亚——你可能比我更了解这一点,绝对不会反对这一点——只要把我的2美分投入进去,万一有人发现它有用的话。
- 所以根据另一个答案,对我的问题的简短回答,从哪里我必须强调,当一个异常从来没有被抛出,是不是,如果不抛出异常并不昂贵。
- 这里有一个简单的基准测试可以帮助您:jsben.ch//fbrd
- developerknowhow.com/364/javascript-trycatch-performance-hit
您在执行典型的CRUD UI代码吗?使用Try-Catch,使用毫无理由地散布在代码中的10000个循环,hell,使用angular/ember-您不会注意到任何性能问题。
如果您正在执行低级库、物理模拟、游戏、服务器端等,那么从不抛出的try-catch块通常根本不重要,但问题是V8在引擎的版本6之前在其优化编译器中不支持它,因此语法上包含try-catch的整个包含函数将不会是最佳的。零能耗。但是,通过创建一个类似于tryCatch的助手函数,您可以轻松地解决这个问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function tryCatch(fun) {
try {
return fun();
}
catch(e) {
tryCatch.errorObj.e = e;
return tryCatch.errorObj;
}
}
tryCatch.errorObj = {e: null};
var result = tryCatch(someFunctionThatCouldThrow);
if(result === tryCatch.errorObj) {
//The function threw
var e = result.e;
}
else {
//result is the returned value
} |
在V8版本6(与node 8.3和最新的chrome一起提供)之后,try-catch中代码的性能与普通代码相同。
- 如果V8就是这样的话,那真的会有所不同,而且您的代码看起来是解决这个问题的一个好主意。你能提供一个链接,说明V8不使用Try-Catch块优化函数吗?你知道这是否适用于其他的JavaScript编译器或解释程序?
- @cpcrack我不确定,在服务器端主要需要try-catch,所以优化不是一个很大的优先级。有关V8源代码,请参见此处,当优化编译器看到函数github.com/v8/v8/blob/master/src/hydrogen.cc l3922-l3927中的try catch时,它会发出警告。
- 请参阅jspef.com/try-catch-performance-overhead
- 但是,并不是所有的函数都可以优化——一些特性会阻止优化编译器在给定的函数上运行(一个"救市方案")。特别是,优化编译器目前使用try catch块来设计函数!资料来源:HTML5岩石
- 为了使答案保持最新,应该注意的是,新的V8涡轮风扇发动机编译器将支持"试捕获"优化,尽管要将其转化为Chrome和Node还需要几个月的时间。参见例如codereview.chromium.org/1996373002
最初的问题是在没有抛出错误时,有关尝试/捕获的成本。当用try/catch保护代码块时,肯定会有影响,但是,当受保护的代码变得更加复杂时,try/catch的影响将很快消失。
考虑这个测试:http://jspef.com/try-catch-performance-jls/2
一个简单的增量以每秒356800000次迭代的速度运行Try/Catch中的相同增量是每秒93500000次迭代。这是75%的开销,因为尝试/捕获。但是,一个普通的函数调用以每秒112200000次迭代的速度运行。2个普通函数调用以每秒61300000次迭代的速度运行。
在这个测试中,一次未执行的尝试比一个简单的函数调用花费的时间稍微多一些。这几乎不是一个速度惩罚,除了在像快速傅立叶变换这样非常激烈的东西的最内部的循环。
您要避免的情况是实际抛出异常的情况。这是非常慢,如上面的链接所示。
编辑:这些数字是我的机器上的铬。在火狐中,未执行的尝试和完全没有保护之间没有显著的区别。如果没有抛出异常,那么使用try/catch基本上是零惩罚。
- 唯一通过信息而不是意见提供答案的答案。
- 对于我来说,Try No Catch是最快的片段,请参见fs5.directupload.net/images/170124/3luf37n3.png
- firefox 50似乎已经进行了尝试/捕获优化,但chrome 55仍然没有,下面是chrome fs5.directupload.net/images/170124/uak7g2j8.png的截图。
据说try-catch区块价格昂贵。但是,如果关键性能不是一个问题,那么使用它就不一定是一个问题。
IMO的处罚是:
可读性:用大量的try-catch给代码添加管道是丑陋和分散注意力的。
不适当:如果代码不受异常崩溃的影响,插入这样的块是一个坏主意。只有在代码中出现故障时才插入它。请看以下主题:何时使用try/catch块?
异步:try-catch块是同步的,在async编程时无效。在ajax请求期间,您在专用回调中处理error和success事件。不需要try-catch。
希望这有帮助,
R.
- "据说是"是道听途说。请提供证据,不要鼓励程序员过早优化。
- 这是胡说八道。有许多"例外"情况不是"失败"。异常是一个强大的编程构造。
- 我测试了假设一个变量是可调用的,而不是先测试它的性能。用if语句验证比用try/catch请求原谅快了几个数量级:jspef.com/try-catch-performance-jls
- 关于异步函数的适当性,现在基本上是默认使用Try-Catch和ES7 AsyncWait组合。您可能希望更新您的答案以反映最近的发展。
- 尝试/捕获方法与异步回调错误处理的另一个重要区别是,在异步回调中意外地抛出错误处理代码(例如,打字错误或难以遗漏的逻辑错误)可能会使进程崩溃,而在catchb中意外地抛出(例如,打字错误或难以遗漏的逻辑错误)锁不会。与通过承诺链处理错误相比,使用await尝试/捕获还具有显著的优势,但这超出了本文的讨论范围。更多信息:gist.github.com/mikermcneil/c028d000cc0cc8bc995a2a82b29245