31

I have read recently some articles (e.g. http://dailyjs.com/2012/09/14/functional-programming/) about the functional aspects of Javascript and the relationship between Scheme and Javascript (the latter was influenced by the first, which is a functional language, while the O-O aspects are inherited from Self which is a prototyping-based language).

However my question is more specific: I was wondering if there are metrics about the performance of recursion vs. iteration in Javascript.

I know that in some languages (where by design iteration performs better) the difference is minimal because the interpreter / compiler converts recursion into iteration, however I guess that probably this is not the case of Javascript since it is, at least partially, a functional language.

mastazi
  • 413

5 Answers5

38

JavaScript does not perform tail recursion optimization, so if your recursion is too deep, you may get a call stack overflow. Iteration doesn't have such issues. If you think you are going to recurse too much, and you really need recursion (for example, to do flood-fill), replace the recursion with your own stack.

Recursion performance is probably worse than iteration performance, because function calls and returns require state preservation and restoration, while iteration simply jumps to another point in a function.

Triang3l
  • 825
22

Update: since ES2015, JavaScript has TCO, so part of the argument below doesn't stand anymore.


Although Javascript doesn't have tail call optimization, recursion is often the best way to go. And sincerely, except in edge cases, you're not going to get call stack overflows.

Performance is something to keep in mind, but premature optimization too. If you think that recursion is more elegant than iteration, then go for it. If it turns out this is your bottleneck (which may never be), then you can replace with some ugly iteration. But most of the times, the bottleneck lies in the DOM manipulations or more generally the I/O, not the code itself.

Recursion is always more elegant1.

1: Personal opinion.

7

I was pretty curious about this performance in javascript as well, so I did some experiments (albeit on an older version of node). I wrote a factorial calculator recursively vs iterations and ran it a few times locally. The result seemed pretty heavily skewed toward recursion having a tax (expected).

Code: https://github.com/j03m/trickyQuestions/blob/master/factorial.js

Result:
j03m-MacBook-Air:trickyQuestions j03m$ node factorial.js 
Time:557
Time:126
j03m-MacBook-Air:trickyQuestions j03m$ node factorial.js 
Time:519
Time:120
j03m-MacBook-Air:trickyQuestions j03m$ node factorial.js 
Time:541
Time:123
j03m-MacBook-Air:trickyQuestions j03m$ node --version
v0.8.22
6

As per request by the OP I'll chip in (without making a fool of myself, hopefully :P)

I think we're all agreed that recursion is just a more elegant way of coding. If done well it can make for more maintainable code, which is IMHO just as important (if not more) that shaving off 0.0001ms.

As far as the argument that JS does not perform Tail-call optimization is concerned: that's not entirely true anymore, using ECMA5's strict mode enables TCO. It was something I wasn't too happy about a while back, but at least I now know why arguments.callee throws errors in strict mode. I know the link above links to a bug report, but the bug is set to WONTFIX. Besides, standard TCO is coming: ECMA6 (December 2013).

Instinctively, and sticking to the functional nature of JS, I'd say that recursion is the more efficient coding style 99.99% of the time. However, Florian Margaine has a point when he says that the bottleneck is likely to be found elsewhere. If you're manipulating the DOM, you're probably best focussing on writing your code as maintainable as possible. The DOM API is what it is: slow.

I think it's nigh on impossible to offer a definitive answer as to which is the faster option. Lately, a lot of jspref's I've seen show that Chrome's V8 engine is ridiculously fast at some tasks, which run 4x slower on FF's SpiderMonkey and vice versa. Modern JS engines have all sorts of tricks up their sleeves to optimize your code. I'm no expert, but I do feel that V8, for example, is highly optimized for closures (and recursion), whereas MS's JScript engine is not. SpiderMonkey often performs better when the DOM is involved...

In short: I'd say which technique will be more performant is, as always in JS, nigh on impossible to predict.

3

Without strict mode, Iteration performance is usually slightly faster then recursion (in addition to making the JIT do more work). Tail recursion optimization essentially eliminates any noticeable difference because it turns the whole call sequence to a jump.

Example: Jsperf

I would suggest worrying much more about code clarity and simplicity when it comes to choosing between recursion and iteration.

Burdock
  • 203