Trigger Optimization 101: Return or Exit()?

Learn when to `return` and when to `exit()` for the best results.

Welcome back to another post in our Trigger Optimization 101 series, where we try and find small tweaks that help you write faster, more efficient triggers. If you're just joining us, make sure to check out our previous post, Trigger Optimization 101: Return Quickly, to learn how to avoid processing waste. Please leave any comments or feedback below, as well as any requests for future topics to cover, and I'll get back to you personally.

If you want to follow along with this week's post, pop on over to the online demo, where you can play in your own sandbox without worrying about taking down production EDAs (leave that to me).

With housekeeping out of the way, let's get started on this week's topic: the proper way to stop trigger execution.

Word Choice Matters

Watch this video (4:24) for a demonstration of this weeks topic: when to use exit (never) versus return (always).

You're trying to end a trigger's execution because the transaction isn't for the right URI or has errored; how do you do end the trigger? We could just make an exit() function call. An example:

exit();
debug('did not end');

Now, this is totally valid, completely functional code. It does exactly what you'd expect it to do: the string 'did not end' is never printed to the Runtime Log. But, we could also write the trigger as follows:

return;
debug('did not end');

Same behavior. So the question is: which is better? Check the video to see exactly how the two vary in terms of performance, but in general, using return is always preferable to using exit(). Back in the old days (*shakes cane at...myself I guess?*) of ExtraHop v3.9, we used SpiderMonkey for our JavaScript interpreter, but with v3.10, we started using V8 under the covers. In addition to making triggers execute faster, also meant we deprecated a few things, one of which was the exit() function, because it is honestly just plain slower.

There are still differences between how exit() and return function though. Take the trigger code below:

functionend() {
exit();
}
end();
debug('the program did not end');

We'll talk more about function use in a later post. For now, this trigger keeps the debug statement from executing just as our first trigger did. We can replace the exit() with a return like so:

functionend() {
return;
}
end();
debug('the program did not end');

Hold up, we're seeing the message on the Runtime Log now, so what gives? When we called exit(), we were ending the entire trigger execution process. When we call return, we are leaving the current function and passing some value to the parent (in this case nothing). If you aren't using functions, which will be 99% of the time, you'll never run into this difference in behavior. If you find yourself needing to replicate exit() behavior though, you can add a simple check and achieve the same results while preserving your performance gains. An example would look like:

A few more lines of code, but if you watch the video, you still save processing cycles over using exit()!

That's all for this week. If you have any old triggers laying around, go check 'em for exit() calls. Bundles uploaded to new systems are automatically scrubbed, but always better to be safe than sorry. We'll be back next week for more trigger optimization goodness.