Titulum
Titulum

Reputation: 11456

Memory leak while using tail-recursion

Imagine I have this hypothetical function (in javascript):

function paginationRecursive(results) {
  let intermediate = retrieveNextPage();
  results = results.concat(intermediate)
  if (haveAllResults()) return results;
  return paginationRecursive(results);
}

Will each value of intermediate be kept in memory until the whole recursive processing has completed, thus everytime increasing memory usage for every recursive call? Or is the engine/gc smart enough to free this memory at any time we go one call "deeper", because it knows that the variable will never be used again?

It could be that it is engine specific (e.g. V8, SpiderMonkey, Chakra, etc.) so in order to make this question not to broad, I prefer to know the answer for the V8 engine.

Upvotes: 0

Views: 301

Answers (1)

Rob Starling
Rob Starling

Reputation: 3908

I think as of right now, the answer is "the intermediate variable should be released, but it won't be".

ES6 does talk about tail-position calls and even requires optimization:

A tail position call must either release any transient internal resources associated with the currently executing function execution context before invoking the target function or reuse those resources in support of the target function.

A decent overview of TCO (tail-call optimization) in JS is http://2ality.com/2015/06/tail-call-optimization.html

That all being said, that page links to this table showing that pretty much no runtimes actually support it: https://kangax.github.io/compat-table/es6/#test-proper_tail_calls_(tail_call_optimisation)

This r/node reddit thread offers some insight and links to this v8 blog post which includes:

[...] the V8 team strongly support denoting proper tail calls by special syntax. There is a pending TC39 proposal called syntactic tail calls to specify this behavior, co-championed by committee members from Mozilla and Microsoft. [...] The V8 team plans to resolve the issue at the next TC39 meeting before shipping implicit proper tail calls or syntactic tail calls by default.

which is to say, V8 doesn't want to implement that ES6 feature as-spec'd and would prefer an explicit syntax for tail-calls, like the ones proposed for TC39

See also: Are functions in JavaScript tail-call optimized?

Upvotes: 1

Related Questions