2

I compared the runtimes of a loop and a recursion, finding out, that the loop is way faster, while not having the problem of running into a RecursionError. Why is it, that loops are so much faster?

def factorial(n):
   if n == 0:
      return n
   else:
      return n + factorial(n-1)

%%timeit -n1000 -r10000
factorial(1000)

163 µs ± 13.2 µs per loop (mean ± std. dev. of 10000 runs, 1000 loops each)

def factorial2(n):
   r = 0
   for i in range(n+1):
      r += i
   return r

%%timeit -n1000 -r10000
factorial2(1000)

The slowest run took 9.46 times longer than the fastest. This could mean that an intermediate result is being cached. 58.7 µs ± 25.2 µs per loop (mean ± std. dev. of 10000 runs, 1000 loops each)

Thanks and happy coding!

semicolon
  • 178
  • 2
  • 11
  • 2
    With recursion in general the runtime has to do extra work pushing variables to the stack frame and then make a function call which adds to the execution time. With recursion even though you are calling the same function over and over, each call creates a new scope of all the local variables. With iteration non of that extra works needs to be done. – jnvilo Feb 23 '19 at 12:44
  • 1
    Your `factorial` is actually calculating the sum between `0 -> n` btw – molamk Feb 23 '19 at 12:47
  • Function calls are quite expensive in Python. One myth is that for-loops are slow in Python, but this is mostly the case if the loop contains function calls or even method calls. See https://wiki.python.org/moin/PythonSpeed/PerformanceTips and https://www.python.org/doc/essays/list2str/ . So `r += i` is quite a lot faster than calling `n + factorial(n-1)`. Btw, shouldn't a *factorial* use multiplication? – Jan Christoph Terasa Feb 23 '19 at 12:48

1 Answers1

2

In general, unless a programming language is specifically made to support fast recursion, recursion is always going to be slower. When the program makes a function call, a new stack frame is created, where all local variables are stored among other things. During the iteration, everything happens inside a single stack frame.

There is something called 'tail recursion', where a function is written in such a way that the result of the calculation is always available in the last frame - so in theory, only 1 stack frame would suffice. In some languages the compiler recognizes this situation and transforms the recursion into iteration 'behind the scenes' - such type of recursion would indeed be equally as fast as iteration. Unfortunately, Python3 doesn't support tail recursion.

dreamcrash
  • 47,137
  • 25
  • 94
  • 117
Zyx
  • 336
  • 4
  • 18