| 1 | # Open an atomic model and close it 100 times and a lot of memory is leaked.
|
|---|
| 2 | # This makes it hard to run nogui scripts on entire Protein Databank.
|
|---|
| 3 | #
|
|---|
| 4 | # Test memory use: chimerax --nogui --silent
|
|---|
| 5 | # Then command "open test_memleak.py"
|
|---|
| 6 | #
|
|---|
| 7 | # Starting chimerax in nogui on macOS 12.4 gives 68 Mbytes memory use reported by Mac Activity Monitor.
|
|---|
| 8 | # For small structure 17gs (0.38 MB cif file) memory use goes to 145 Mbytes.
|
|---|
| 9 | # For larger structure 7azs (42 MB cif file) memory use goes to 526 Mbytes.
|
|---|
| 10 | # For a PDB format file 1s72 (9 MB pdb file) memory use goes to 1450 Mbytes.
|
|---|
| 11 | # For EMDB map 1080 (4 MB ccp4 file) memory use goes to 71 Mbyte.
|
|---|
| 12 | # For 7azs opening without adding to open models memory use goes to 280 Mbytes.
|
|---|
| 13 | #
|
|---|
| 14 | import tracemalloc
|
|---|
| 15 | tm_style = 'lineno'
|
|---|
| 16 | tracemalloc.start(1 if tm_style == 'lineno' else 15)
|
|---|
| 17 | n = 10
|
|---|
| 18 | from time import time
|
|---|
| 19 | from chimerax.core.commands import run
|
|---|
| 20 | from chimerax.mmcif import open_mmcif
|
|---|
| 21 | import gc
|
|---|
| 22 | path = '/Users/goddard/Downloads/ChimeraX/PDB/7azs.cif'
|
|---|
| 23 | # open and close model once so that tracemalloc does not see
|
|---|
| 24 | # related module imports as a "memory leak"
|
|---|
| 25 | models = run(session, 'open 7azs')
|
|---|
| 26 | session.models.close(models)
|
|---|
| 27 | del models
|
|---|
| 28 | gc.collect()
|
|---|
| 29 | snap1 = tracemalloc.take_snapshot()
|
|---|
| 30 | for i in range(n):
|
|---|
| 31 | t0 = time()
|
|---|
| 32 | # models = run(session, 'open 17gs')
|
|---|
| 33 | models = run(session, 'open 7azs')
|
|---|
| 34 | # models = run(session, 'open 1s72 format pdb')
|
|---|
| 35 | # models = run(session, 'open 1080 from emdb')
|
|---|
| 36 | session.models.close(models)
|
|---|
| 37 | # models = open_mmcif(session, path)[0]
|
|---|
| 38 | # for s in models:
|
|---|
| 39 | # s.delete()
|
|---|
| 40 | t1 = time()
|
|---|
| 41 | if i % 10 == 0:
|
|---|
| 42 | print ('%d %.2f' % (i, t1-t0))
|
|---|
| 43 | # print ('%d %.2f %d' % (i, t1-t0, len(gc.garbage)))
|
|---|
| 44 | del models
|
|---|
| 45 | snap2 = tracemalloc.take_snapshot()
|
|---|
| 46 | top_stats = snap2.compare_to(snap1, tm_style)
|
|---|
| 47 | for i, stat in enumerate(top_stats[:5]):
|
|---|
| 48 | if tm_style == 'lineno':
|
|---|
| 49 | print(f"#{i+1} {stat}")
|
|---|
| 50 | else:
|
|---|
| 51 | print(f"#{i+1}:")
|
|---|
| 52 | for line in stat.traceback.format():
|
|---|
| 53 | print(line)
|
|---|
| 54 | print()
|
|---|
| 55 | """
|
|---|
| 56 | gc.collect()
|
|---|
| 57 | from chimerax.atomic.molobject import _weak_refs as wr
|
|---|
| 58 | alive = [x for x in wr if x() is not None]
|
|---|
| 59 | print(len(alive), "live references")
|
|---|
| 60 | import sys
|
|---|
| 61 | print([(x().__class__.__name__, sys.getrefcount(x())) for x in alive])
|
|---|
| 62 | """
|
|---|