4

Description of my question

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:

What I got as output

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

What I expected as output

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
  ^^^^^^^^^^^^^^^^^^

Minimal code sample

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)])
Ytsen de Boer
  • 2,797
  • 2
  • 25
  • 36

1 Answers1

5

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))