I'm trying to chase down a memory leak in a python 3.6 program.
For that I'm testing tracemalloc, which allows me to compare memory snapshots and print out a "backtrace".
The max number of frames in the backtrace should be set as the first argument to tracemalloc.start()
, according to the docs.
However, in my minimal test setup (code below) I start tracemalloc with argument 25, but I only get 1 frame in the backtrace, where I would expect 2:
me@my_machine:/tmp$ python ./test_tm.py
Entry: /tmp/test_tm_utils.py:2: size=3533 KiB (+3533 KiB), count=99746 (+99746), average=36 B
Traceback:
/tmp/test_tm_utils.py:2
I would expect two lines, like so:
Entry: /tmp/test_tm_utils.py:2: size=3533 KiB (+3533 KiB), count=99746 (+99746), average=36 B
Traceback:
/tmp/test_tm_utils.py:2
/tmp/test_tm.py:10
^^^^^^^^^^^^^^^^^^
Main program in _/tmp/test_tm.py_:
import tracemalloc
tracemalloc.start(25)
import test_tm_utils
if __name__ == '__main__':
s1 = tracemalloc.take_snapshot()
test_tm_utils.myfun()
s2 = tracemalloc.take_snapshot()
diff = s2.compare_to(s1, 'lineno')
for entry in diff[:1]:
print('\nEntry: {}'.format(entry))
print('Traceback:')
for line in entry.traceback:
print(' {}'.format(line))
And the memory leak function in test_tm_utils.py
:
def myfun(lst=list()):
lst.append([i for i in range(100000)])
The secret is the key_type parameter. You must use the value "traceback"
to get all the lines specified in tracemalloc.start()
. If you use "lineno"
or "filename"
you only get one line.
This is true for both Statistics or in your case compare_to.
So your code should look something like this:
s2 = tracemalloc.take_snapshot()
diff = s2.compare_to(s1, 'traceback') # This is the only change
for entry in diff[:1]:
print('\nEntry: {}'.format(entry))
print('Traceback:')
for line in entry.traceback:
print(' {}'.format(line))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With