Memory Leak in actor.slicer
Hi there,
thank you again for the nice work!
While using this, I have noticed a memory leak in lines 136-143 of preview.py, so when using actor.slicer.
You can reproduce this using the following code:
import tracemalloc
import linecache
from totalsegmentator.python_api import totalsegmentator
def filter_mem(snapshot):
return snapshot.filter_traces((
tracemalloc.Filter(False, "<frozen importlib._bootstrap>"),
tracemalloc.Filter(False, "<frozen importlib._bootstrap_external>"),
tracemalloc.Filter(False, "<unknown>"),
))
def display_top(snapshot, key_type='lineno', limit=10):
top_stats = filter_mem(snapshot).statistics(key_type)
unit = "MiB"
if unit == "GiB":
factor = 1.074e+9
elif unit == "MiB":
factor = 1.049e+6
elif unit == "KiB":
factor = 1024
print("Top %s lines" % limit)
for index, stat in enumerate(top_stats[:limit], 1):
frame = stat.traceback[0]
print("#%s: %s:%s: %.1f "
% (index, frame.filename, frame.lineno, stat.size / factor) + unit)
line = linecache.getline(frame.filename, frame.lineno).strip()
if line:
print(' %s' % line)
other = top_stats[limit:]
if other:
size = sum(stat.size for stat in other)
print(f"Number of other {len(other)}, size: {size / factor:.3f} {unit}")
total = sum(stat.size for stat in top_stats)
print(f"Total allocated size: {total / factor:.3f} {unit}")
if __name__ == "__main__":
tracemalloc.start(30)
presnapshot = tracemalloc.take_snapshot()
totalsegmentator(
input="/data/s1212.nii.gz",
output="/data/totalseg",
preview=True,
)
postsnapshot = tracemalloc.take_snapshot()
for s in filter_mem(postsnapshot).compare_to(filter_mem(presnapshot), "lineno")[:10]:
print(s)
input("Press to stop")
Here is my output, as you see there is a lot of still occupied memory when the function is done:
/usr/local/lib/python3.8/dist-packages/nibabel/dataobj_images.py:373: size=123 MiB (+123 MiB), count=3 (+3), average=41.0 MiB
/usr/local/lib/python3.8/dist-packages/fury/actor.py:165: size=123 MiB (+123 MiB), count=3 (+3), average=41.0 MiB
...
If you remove those lines, the output is the following:
/usr/local/lib/python3.8/dist-packages/scipy/_lib/doccer.py:69: size=703 KiB (+703 KiB), count=225 (+225), average=3202 B
/usr/lib/python3.8/abc.py:85: size=689 KiB (+689 KiB), count=2514 (+2514), average=281 B
/usr/lib/python3.8/linecache.py:137: size=491 KiB (+491 KiB), count=4863 (+4863), average=103 B
/usr/lib/python3.8/inspect.py:2819: size=398 KiB (+398 KiB), count=5219 (+5219), average=78 B
/usr/local/lib/python3.8/dist-packages/matplotlib/_docstring.py:40: size=386 KiB (+386 KiB), count=122 (+122), average=3237 B
/usr/lib/python3.8/abc.py:102: size=369 KiB (+369 KiB), count=3483 (+3483), average=108 B
/usr/lib/python3.8/typing.py:764: size=329 KiB (+329 KiB), count=1891 (+1891), average=178 B
/usr/local/lib/python3.8/dist-packages/matplotlib/colors.py:1100: size=245 KiB (+245 KiB), count=6221 (+6221), average=40 B
/usr/local/lib/python3.8/dist-packages/attr/_make.py:301: size=229 KiB (+229 KiB), count=2360 (+2360), average=99 B
/usr/local/lib/python3.8/dist-packages/matplotlib/artist.py:140: size=220 KiB (+220 KiB), count=3516 (+3516), average=64 B
...
In my experience, after running the script multiple times, the usage of the program just keeps on increasing and the memory never gets released. For example, after one run with those lines:
CONTAINER ID NAME CPU % MEM USAGE
6032e76bb495 totalseg 0.03% 2.951GiB
after two runs
CONTAINER ID NAME CPU % MEM USAGE
6032e76bb495 totalseg 0.03% 2.969GiB
after 15 runs
CONTAINER ID NAME CPU % MEM USAGE
6032e76bb495 totalseg 0.03% 6.295GiB
Thank you very much.
Best, Giulia
Thanks for pointing this out. Unfortunately I am not very familiar with fury and vtk (those libraries provide the actor). I tried a few things but that did not change anything. For me the memory leak also does not increase over several runs.
@wasserth how did you test it? I did something like this
presnapshot = tracemalloc.take_snapshot()
for _ in range(15):
totalsegmentator(
input="/data/s1212.nii.gz",
output="/data/totalseg",
preview=True,
)
postsnapshot = tracemalloc.take_snapshot()
And do you also get a similar output for tracemalloc?
I did the same and i get this output:
Have you also tried with a bigger image?