So was playing around with memory_profiler module and noticed something weird. I was working on a function used to find nCr combinations using recursion. I made 2 version of of my function :
ver 1:
@profile def c(n, r, memo={}): pair = (n, r) if pair in memo: return memo[pair] if r == 1: return n if n - r < r: return c(n, n - r) if r == 0 or r == n: return 1 return c(n - 1, r - 1) + c(n - 1, r) print(c(20, 10))
ver 2:
@profile def c(n, r, memo={}): pair = (n, r) if pair in memo: return memo[pair] if r == 1: return n if n - r < r: return c(n, n - r) if r == 0 or r == n: return 1 memo[pair] = c(n - 1, r - 1) + c(n - 1, r) return memo[pair] print(c(20, 10))
memory_profiler :
As you can see ver 1 and ver 2 are the same except for the last 2 lines of the function. But running memory_profiler on them they have great difference in performance. The thing I'm most puzzled by is although I forgot to pass memo in the function call it still results in such great performance improvement.
Each function call results in a new empty memo dict for that function. So why does line 8 in version 1 evaluates as False and fails to return whereas the same line in ver 2 evaluates True and returns 36 times. Shouldn't they both realistically be false as I'm trying to find key in an empty dictionary ? Shouldn't there be virtually no observable difference in performance ?