performance of recursive generator

Steven Bethard steven.bethard at gmail.com
Thu Aug 11 19:49:26 EDT 2005


aurora wrote:
> This test somehow water down the n^2 issue. The problem is in the depth 
> of  recursion, in this case it is only log(n). It is probably more 
> interesting  to test:
> 
> def gen(n):
>      if n:
>          yield n
>          for i in gen(n-1):
>              yield i

You should be able to do this yourself ;) but here's the results anyway:

-------------------- test.py --------------------
def gen(n):
     if n:
         yield n
         for i in gen(n-1):
         	yield i

def gen_wrapper(n):
     return list(gen(n))

def nongen(n, func):
	if n:
	    func(n)
	    nongen(n-1, func)

def nongen_wrapper(n):
	result = []
	nongen(n, result.append)
	return result
-------------------------------------------------

D:\steve>python -m timeit -s "import test" "test.gen_wrapper(10)"
10000 loops, best of 3: 22.3 usec per loop

D:\steve>python -m timeit -s "import test" "test.nongen_wrapper(10)"
100000 loops, best of 3: 12 usec per loop

D:\steve>python -m timeit -s "import test" "test.gen_wrapper(20)"
10000 loops, best of 3: 60.8 usec per loop

D:\steve>python -m timeit -s "import test" "test.nongen_wrapper(20)"
10000 loops, best of 3: 20.9 usec per loop

D:\steve>python -m timeit -s "import test" "test.gen_wrapper(100)"
1000 loops, best of 3: 1.01 msec per loop

D:\steve>python -m timeit -s "import test" "test.nongen_wrapper(100)"
10000 loops, best of 3: 93.3 usec per loop

It does appear that you get O(N**2)-ish behavior, but the difference 
isn't horribly noticeable at a depth of 10 or 20.  How deep are your trees?

I also have to mention that, for this kind of problem, it's silly to use 
any recursive solution, when there's a faster non-recursive solution:

-------------------- test.py --------------------
...
def nonrecur(n):
     result = []
     append = result.append
     while n:
         append(n)
         n -= 1
     return result
-------------------------------------------------

D:\steve>python -m timeit -s "import test" "test.nonrecur(10)"
100000 loops, best of 3: 6.26 usec per loop

D:\steve>python -m timeit -s "import test" "test.nonrecur(100)"
10000 loops, best of 3: 37.9 usec per loop

Sure, this only works on non-branching trees, but if that's what you're 
worried about, use the solution designed for it. ;)

STeVe



More information about the Python-list mailing list