6 ms·
The V8 performance issue with try/catch is widely misunderstood, and it causes people to unnecessarily avoid using it. try/catch can slow down code in the same
by ef4 15y ago
The V8 performance issue with try/catch is widely misunderstood, and it causes people to unnecessarily avoid using it.
try/catch can slow down code in the same function as the try/catch statements. But it doesn't slow down any other function called from within there. In other words, it only affects the stack frame at which the try/catch statement actually appears.
So if you have some top level error trapping function like:
errorCatcher = function(continuation){
try {
continuation();
catch(err){
reportErrorToServer(err);
}
}
and you only call it once at every entry point to your code, the impact will be totally undetectable, because there's only a single function invocation within the unoptimizable area.
I encourage people to performance test the difference caused by try/catch like this. You'll see that it doesn't hurt at all. It's only a problem if you actually write a try statement within some tight inner-loop function.
- gruseom 15y ago(Rewritten to report results) I tried the following 4 variations in Node.js 0.6.13, V8 3.6.6.24. (The "global" business is for accessing the functions from a REPL.) var lots = 1000000; // A: try/catch inside loop global.a = function () { for (var i=0; i<lots; i++) { try { } catch (e) { } } } // B: one try/catch, inlined loop global.b = function () { try { for (var i=0; i<lots; i++) { } } catch (e) { } } // C: one try/catch, loop in local function global.c = function () { var loop = function () { for (var i=0; i<lots; i++) { } } try { loop(); } catch (e) { } } // D: one try/catch, loop in top-level function function loop () { for (var i=0; i<lots; i++) { } } global.d = function () { try { loop(); } catch (e) { } } // E: no try/catch global.e = function () { loop(); } global.time = function (times, fn) { var start = new Date().getTime(); for (var i=0; i<times; i += 1) { fn(); } return (new Date().getTime() - start) / times; }; In the REPL: > ({ a : time(100,a), b : time(100,b), c : time(100,c), d : time(100,d), e : time(100,e) }); { a 7.66 b 5.29 c 5.06 d 1.45 e 1.32 } So a million try/catches (A) is bad. But hoisting the try outside the loop (B) or putting the loop into a local function (C) doesn't do nearly as well as putting the loop in an outside function (D), which is almost as fast as no try/catch at all (E). I tried a few variations (like making the loop actually do some work) and the outcomes were all comparable. This clarifies and confirms what ef4 said: don't put cpu-intensive code inside the same function as a try/catch. Put it somewhere else and call it. Also, local functions don't necessarily count as "somewhere else".
- rakeshpai 15y agoThis is what I meant, though I guess I could've used a better term than "code paths". Thanks for clarifying this anyway. :)
- deleted 15y ago[deleted]