I'm digging into the node 7 async/await feature and keep stumbling across code like this
function getQuote() {
let quote = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
return quote;
}
async function main() {
try {
var quote = await getQuote();
console.log(quote);
} catch (error) {
console.error(error);
}
}
main();
This seems to be the only possibility resolve/reject or return/throw with async/await, however, v8 doesn't optimise code within try/catch blocks?!
Are there alternatives?
Answer
Alternatives
An alternative to this:
async function main() {
try {
var quote = await getQuote();
console.log(quote);
} catch (error) {
console.error(error);
}
}
would be something like this, using promises explicitly:
function main() {
getQuote().then((quote) => {
console.log(quote);
}).catch((error) => {
console.error(error);
});
}
or something like this, using continuation passing style:
function main() {
getQuote((error, quote) => {
if (error) {
console.error(error);
} else {
console.log(quote);
}
});
}
Original example
What your original code does is suspend the execution and wait for the promise returned by getQuote()
to settle. It then continues the execution and writes the returned value to var quote
and then prints it if the promise was resolved, or throws an exception and runs the catch block that prints the error if the promise was rejected.
You can do the same thing using the Promise API directly like in the second example.
Performance
Now, for the performance. Let's test it!
I just wrote this code - f1()
gives 1
as a return value, f2()
throws 1
as an exception:
function f1() {
return 1;
}
function f2() {
throw 1;
}
Now let's call the same code million times, first with f1()
:
var sum = 0;
for (var i = 0; i < 1e6; i++) {
try {
sum += f1();
} catch (e) {
sum += e;
}
}
console.log(sum);
And then let's change f1()
to f2()
:
var sum = 0;
for (var i = 0; i < 1e6; i++) {
try {
sum += f2();
} catch (e) {
sum += e;
}
}
console.log(sum);
This is the result I got for f1
:
$ time node throw-test.js
1000000
real 0m0.073s
user 0m0.070s
sys 0m0.004s
This is what I got for f2
:
$ time node throw-test.js
1000000
real 0m0.632s
user 0m0.629s
sys 0m0.004s
It seems that you can do something like 2 million throws a second in one single-threaded process. If you're doing more than that then you may need to worry about it.
Summary
I wouldn't worry about things like that in Node. If things like that get used a lot then it will get optimized eventually by the V8 or SpiderMonkey or Chakra teams and everyone will follow - it's not like it's not optimized as a principle, it's just not a problem.
Even if it isn't optimized then I'd still argue that if you're maxing out your CPU in Node then you should probably write your number crunching in C - that's what the native addons are for, among other things. Or maybe things like node.native would be better suited for the job than Node.js.
I'm wondering what would be a use case that needs throwing so many exceptions. Usually throwing an exception instead of returning a value is, well, an exception.
No comments:
Post a Comment