ChatGPT解决这个技术问题 Extra ChatGPT

In Javascript, is it expensive to use try-catch blocks even if an exception is never thrown?

Is it "slow" to use several try-catch blocks when no exceptions are thrown in any of them? My question is the same as this one, but for JavaScript.

Suppose I have 20 functions which have try-catch blocks in them and another function that calls every one of those 20 functions where none of them throw an exception. Will my code execute slower or perform much worse because of this try-catch blocks?

@Chase: but doesn't that talk about when exceptions are caught?
@Qantas94Heavy - There are a lot of good Try/Catch performance tests on jsperf: jsperf.com/search?q=Try/Catch. In most cases the try is fairly negligible, but that depends a bit on your definition of slow. If you're looking for performance, then there are much better options then try/catch. @Roland does a good job of listing a few more good reasons not to use them as well.
@Chase Well 99% of jsperfs are broken and at other times they are misleading and don't give useful info. Of course a function that barely does anything is only slightly less slower with a try catch.
So according to the other answer, short answer to my question, from where I must highlight when an exception is never thrown, is NO, it's not expensive if exceptions are not thrown.

E
Esailija

Are you doing typical CRUD UI code? Use try catches, use loops that go to 10000 for no reason sprinkled in your code, hell, use angular/ember - you will not notice any performance issue.

If you are doing low level library, physics simulations, games, server-side etc then the never throwing try-catch block wouldn't normally matter at all but the problem is that V8 didn't support it in their optimizing compiler until version 6 of the engine, so the entire containing function that syntactically contains a try catch will not be optimized. You can easily work around this though, by creating a helper function like tryCatch:

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
}

After V8 version 6 (shipped with Node 8.3 and latest Chrome), the performance of code inside try-catch is the same as that of normal code.


If that's the case with V8, that would really make a difference, and your code looks like a good idea to solve that issue. Could you provide a link with the source of that information that states that V8 doesn't optimize functions with try-catch blocks? Do you know if that applies to other Javascript compilers or interpreters?
@cprcrack I don't know for sure, try catch is mostly needed on server side so it would not be a huge priority to optimize. See here for V8 source where optimizing compiler bails out when it sees try catch in a function github.com/v8/v8/blob/master/src/hydrogen.cc#L3922-L3927
"Not all functions can be optimized, however - some features prevent the optimizing compiler from running on a given function (a "bail-out"). In particular, the optimizing compiler currently bails out on functions with try {} catch {} blocks!" Source: html5rocks
For the sake of keeping the answer up to date, it should be noted that the new V8 TurboFan compiler will support try-catch optimization, though it is still a few months from making it into Chrome and Node. See e.g. codereview.chromium.org/1996373002
a
asthomas

The original question asked about the cost of try/catch when an error was not thrown. There is definitely an impact when protecting a block of code with try/catch, but the impact of try/catch will vanish quickly as the code being protected becomes even slightly complex.

Consider this test: http://jsperf.com/try-catch-performance-jls/2

A simple increment runs at 356,800,000 iterations per second The same increment within a try/catch is 93,500,000 iterations per second. That's on overhead of 75% due to try/catch. BUT, a trivial function call runs at 112,200,000 iterations per second. 2 trivial function calls run at 61,300,000 iterations per second.

An un-exercised try in this test takes slightly more time than one trivial function call. That's hardly a speed penalty that matters except in the inner-most loop of something really intense like an FFT.

The case you want to avoid is the case where an exception is actually thrown. That is immensely slower, as shown in the above link.

Edit: Those numbers are for Chrome on my machine. In Firefox there is no significant difference between an unexercised try and no protection at all. There's essentially zero penalty to using try/catch if no exception is thrown.


The only answer that actually provided an answer through information instead of opinions.
for me try-no-catch is the fastest snippet, see fs5.directupload.net/images/170124/3luf37n3.png
firefox 50 seems to have try/catch optimization already, but chrome 55 still not, here is the screenshot for chrome fs5.directupload.net/images/170124/uak7g2j8.png
The link jsperf.com/try-catch-performance-jls/2 does'nt work anymore.
jsperf went off-line a couple of years ago. Nothing to be done about that.
C
Community

The try-catch block is said to be expensive. However if critical performance is not an issue, using it is not necessarily a concern.

The penalty IMO is:

readability

inappropriate in many cases

ineffective when it comes to async programming

Readability: plumbing your code with plenty of try-catch is ugly and distracting

inappropriate: it's a bad idea to insert such block if your code is not subject to exception-crash. Insert it only if you expect a failure in your code. Take a look at the following topic: When to use try/catch blocks?

Async: the try-catch block is synchronous and is not effective when it comes to async programming. During an ajax request you handle both the error and success events in dedicated callbacks. No need for try-catch.

Hope this helps,

R.


"Is said to be" is hearsay. Please provide evidence, don't encourage programmers to prematurely optimize.
This is bollocks. There are many "exceptional" situations that are not a "failure". Exceptions are a powerful programming construct.
I tested the performance of assuming a variable is callable versus testing it first. Verifying with an if statement was orders of magnitude faster than begging for forgiveness with a try/catch: jsperf.com/try-catch-performance-jls
Regarding appropriateness in async functions, it's basically now the default to use try catch combined with ES7 async await. You may want to update your answer to reflect that recent development.
Another significant to a try/catch approach vs. error handling with asynchronous callbacks is that accidentally throwing (e.g. a typo or hard-to-miss logic error) in the error handling code within your asynchronous callback will probably crash the process, whereas accidentally throwing (e.g. a typo or hard-to-miss logic error) in a catch block will not. There are also significant advantages to try/catch with await vs. error handling via promise chaining, but that's out of scope of this comment. More on that: gist.github.com/mikermcneil/c1028d000cc0cc8bce995a2a82b29245
A
Akseli Palén

I attempt to provide an answer based on concrete benchmark results. For that I wrote a simple benchmark that compares try-catch to various if-else conditions from simple to more complex. I understand that benchmarks might change a lot depending on the platform. Please comment if you get different results. See the try-catch benchmark here.

First, I try to represent the test suite here in a compact manner. See the link above for full details. There are four test cases, referred later by (index):

(1) try-catch block that calls a function lib.foo with a bit of trigonometric math. No error is ever thrown.

(2) if-else block that checks the existence of the function by 'foo' in lib and then calls the function.

(3) if-else block that checks the existence of the function by typeof lib['foo'] === 'function' and then calls the function.

(4) if-else block that checks the existence of the function by Object.prototype.hasOwnProperty.call(lib, 'foo') and then calls the function.

I ran the benchmark a few times on Chrome 87. Although the actual numbers changed from time to time, the results were consistent and can be roughly summarised as follows:

The try-catch (1) and if-else (2) were almost equivalent in run time. The try-catch (2) was sometimes slower by 1% to 2%.

The if-else (3) was 75% slower than try-catch (1) or if-else (2).

The if-else (4) was 90% slower than try-catch (1) or if-else (2).

To clarify, 75% slower means that if the fastest case took 1.0 secs then the 75% slower execution took 1.75 seconds.

As a conclusion, using try-catch in the case where error is never thrown seems to be as efficient as checking any simple condition. If the condition has anything more complex, try-catch is significantly faster.

As a personal note, the conclusion is in line with what I was taught at university. Although it was in the context of C++ the same lesson seems to apply here. If I remember correctly, my lecturer said that try-block was designed to be very efficient, almost invisible efficiency-wise. However, it was the catch-block that was slow and I mean really slow. If an error was thrown then the handling with catch-block took hundreds or even thousands times longer than what could be achieved with if-else block. Therefore, keep your exceptions exceptional.


Just for fun, I tried substituting the line if ('foo' in lib) { in the benchmark with if (lib.foo) { in case in was looping through expensively and, though there are only three properties (maybe it'd change in a complex enough object?), the lib.foo check was 79% slower than in. Bizarre [to me]. Anyhow, yes, benchmarking is always The Right Way to actually find out! Thanks for setting one up.
@ruffin, does ``` 'foo' in lib ``` check for null values and zeros? Or it only works against undefined? Just curios :)