python - Hidden references to function arguments causing big memory usage? -
edit: never mind, being stupid.
i came across code recursion on smaller , smaller substrings, here's essence plus testing stuff:
def f(s): if len(s) == 2**20: input('check memory usage again') else: f(s[1:]) input('check memory usage, press enter') f('a' * (2**20 + 500))
before call, python process takes 9 mb (as checked windows task manager). after 500 levels ~1mb strings, it's @ 513 mb. no surprise, each call level still holding on string in s
variable.
but tried fix replacing reference string reference new string , still goes 513 mb:
def f(s): if len(s) == 2**20: input('check memory usage again') else: s = s[1:] f(s) input('check memory usage, press enter') f('a' * (2**20 + 500))
why doesn't let go off memory? strings smaller, later strings fit space of earlier strings. there hidden additional references strings somewhere or going on?
i had expected behave this, goes 10 mb (a change of 1 mb, expected because new string built while old string still exists):
input('check memory usage, press enter') s = 'a' * (2**20 + 500) while len(s) != 2**20: s = s[1:] input('check memory usage again')
(never mind poor time complexity, btw, know that, don't bother.)
your function recursive, when call f()
, current frame put onto stack, , new 1 created. each function call keeps reference new string creates pass down next call.
to illustrate stack
import traceback def recursive(x): if x: recursive(x[1:]) else: traceback.print_stack() recursive('abc')
gives
$ python tmp.py file "tmp.py", line 10, in <module> recursive('abc') file "tmp.py", line 5, in recursive recursive(x[1:]) file "tmp.py", line 5, in recursive recursive(x[1:]) file "tmp.py", line 5, in recursive recursive(x[1:]) file "tmp.py", line 7, in recursive traceback.print_stack()
when final call recursive()
returns, returns next call above still has reference x
.
but tried fix replacing reference string reference new string , still goes 513 mb
well did in current function being called, function called still has reference passed in. e.g.
def foo(x): print "foo1", locals() bar(x) print "foo2", locals() def bar(x): print "bar1", locals() x = "something else" print "bar2", locals() foo('original thing')
when foo()
called, passes string 'original thing'
bar()
. , though bar()
gets rid of reference, current call above foo()
still has reference
$ python tmp_x.py foo1 {'x': 'original thing'} bar1 {'x': 'original thing'} bar2 {'x': 'something else'} foo2 {'x': 'original thing'}
i hope illustrates it. have been little vague in first statement stack frames.
Comments
Post a Comment