http://www.perlmonks.org?node_id=11108774

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Memory stays fixed:
$|++; while () { print '.'; select undef,undef,undef,0.01; }
Memory use grows:
$|++; re(); sub re { print '.'; select undef,undef,undef,0.01; re() }
What's going on?

Replies are listed 'Best First'.
Re: sub calls and memory use
by Corion (Patriarch) on Nov 16, 2019 at 07:15 UTC

    The call stack grows.

    Perl does not implement "tail call optimization" automatically.

    If you want this, you need to do it manually, by using goto:

    $|++; re(); sub re { print '.'; select undef,undef,undef,0.01; goto &re; }

    or

    use 5.016; $|++; re(); sub re { print '.'; select undef,undef,undef,0.01; goto __SUB__; }
      Addendum: NB: like this any extra return will now jump directly to the first call, because of the bypassing of the call stack.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      update

      Reworded

      What if you need to pass an arg to the sub? Even empty parens with goto cause memory growth. I got around it by changing a global var instead of passing args but is there a more proper way? Thanx

        See goto. You pass arguments in @_, as always.

        Of course, when calling any function, the call stack still grows since the return address needs to be stored on the call stack. This is independent of any function parameters (or none) passed to the next recursive invocation.

        Update: As the replies below also point out, I answered too quickly. I thought you were still calling the function but with empty parameters. If you're using goto to transfer control to the function, there should be no memory growth, as the replies also say.

A reply falls below the community's threshold of quality. You may see it by logging in.