This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: python3.2 memory leak when reloading class with attributes
Type: resource usage Stage: resolved
Components: Versions: Python 3.3
process
Status: closed Resolution: out of date
Dependencies: Superseder:
Assigned To: Nosy List: Arfrever, amaury.forgeotdarc, benjamin.peterson, ezio.melotti, jcea, kaizhu, pitrou, terry.reedy
Priority: normal Keywords:

Created on 2011-05-14 07:16 by kaizhu, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (6)
msg135961 - (view) Author: kai zhu (kaizhu) Date: 2011-05-14 07:16
i'm using the latest debian unstable python3.2 build on colinux (2011, may, 14)

## leak.py
## >>> import imp, leak; imp.reload(leak)
## will leak ~2.5mb per reload
## on i386 debian unstable machine (according to top).
## in my real world app (an automatic build system),
## i run out of memory after a number reloads :(
class Foo(object): pass
Foo.leaky_dictionary = {}
for aa in range(256):
  for bb in range(256):
    Foo.leaky_dictionary[(bb << 8) | aa] = None


$ python3.2
Python 3.2.1a0 (default, May  5 2011, 00:47:12)
[GCC 4.6.1 20110428 (prerelease)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import imp, leak; imp.reload(leak) ## 11mb
<module 'leak' from 'leak.py'>
>>> import imp, leak; imp.reload(leak) ## 13mb
<module 'leak' from 'leak.py'>
>>> import imp, leak; imp.reload(leak) ## 16mb
<module 'leak' from 'leak.py'>
>>> import imp, leak; imp.reload(leak) ## 19mb
<module 'leak' from 'leak.py'>
msg135963 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2011-05-14 07:55
I think this has to do with class attributes and reload():

wolf@hp:~/dev/py/py3k$ cat leak.py
class Foo: pass
Foo.l = list(range(65535))

wolf@hp:~/dev/py/py3k$ ./python 
Python 3.3a0 (default:4b122cac7ac5+, May 14 2011, 10:01:13) 
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import imp, leak; imp.reload(leak)
<module 'leak' from 'leak.py'>
[189091 refs]
>>> imp.reload(leak)
<module 'leak' from 'leak.py'>
[254649 refs]
>>> imp.reload(leak)
<module 'leak' from 'leak.py'>
[320207 refs]
>>> imp.reload(leak)
<module 'leak' from 'leak.py'>
[385765 refs]
>>> import gc; gc.collect()
28
[123927 refs]

However calling gc.collect() explicitly seems to fix the problem.
msg135964 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2011-05-14 08:00
It's simply because all classes form a cycle (Foo -> Foo.__mro__ -> Foo)
A class and class attributes can only be freed with gc.collect().
Did you disable the garbage collector?
msg136020 - (view) Author: kai zhu (kaizhu) Date: 2011-05-15 08:14
explicit gc.collect() doesn't seem to fix the leak in my application.
my current fix is to not re-instantiate the class attribute (which cost ~7mb) during reload & instead reference one created earlier.

i haven't pinpointed y, but i suspect its a corner case, which would rarely occur in general usage.  my class also inherits from subprocess.Popen, which has a __del__ method, which might interfere w/ collection (although gc.garbage says otherwise ;).

the reason i reload is that the script gets modified frequently, which the auto-build system will detect & reload.
msg136479 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2011-05-21 20:34
> my class also inherits from subprocess.Popen, which has a __del__ method, which might interfere w/ collection

The doc says __del__ *will* prevent collection.

> (although gc.garbage says otherwise ;).

Do you mean that gc.garbage is empty, when it should not be?

Have you tried replacing __del__ with an explicit close or cleanup method?
msg194942 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-08-12 11:25
Yes, __del__ will interfere with garbage collection before Python 3.4. This is pretty much expected (and is fixed in Python 3.4, but won't be backported).
History
Date User Action Args
2022-04-11 14:57:17adminsetgithub: 56284
2013-08-12 11:25:53pitrousetresolution: wont fix -> out of date
2013-08-12 11:25:49pitrousetstatus: open -> closed

versions: - Python 3.4
nosy: + pitrou

messages: + msg194942
resolution: wont fix
stage: resolved
2013-06-30 06:01:59terry.reedysetversions: + Python 3.4, - Python 3.2
2012-09-18 06:59:59Arfreversetnosy: + Arfrever
2012-09-15 23:18:01ezio.melottisetnosy: + benjamin.peterson
2011-05-21 20:34:04terry.reedysetnosy: + terry.reedy

messages: + msg136479
title: python3.2 memory leak when setting integer key in dictionary -> python3.2 memory leak when reloading class with attributes
2011-05-16 12:54:36jceasetnosy: + jcea
2011-05-15 08:14:42kaizhusetmessages: + msg136020
2011-05-14 08:00:27amaury.forgeotdarcsetnosy: + amaury.forgeotdarc
messages: + msg135964
2011-05-14 07:55:54ezio.melottisetnosy: + ezio.melotti

messages: + msg135963
versions: + Python 3.3
2011-05-14 07:16:31kaizhucreate