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:
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.
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".
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:
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.