【问题标题】:How to free memory of python deleted object?如何释放python删除对象的内存?
【发布时间】:2016-11-27 11:31:09
【问题描述】:

似乎python3.5并没有完全释放任何已删除对象的内存,这可能是因为python内部维护了某种内存池以用于重用目的,但是,我不想重用它们,我想释放它们为在 linux 上运行的其他程序提供内存。

>>> psutil.Process().memory_info().rss / 2**20
11.47265625
>>> d = {x:x for x in range(10**7)}
>>> psutil.Process().memory_info().rss / 2**20
897.1796875
>>> del d
>>> gc.collect()
0
>>> psutil.Process().memory_info().rss / 2**20
15.5859375

这只是一个玩具示例,真正的问题是在一个正在运行的服务器上,占用了 20GB 的不可释放内存。

这是另一个例子:(wd1 是带有字符串键的 dict 的 dict)

>>> psutil.Process().memory_info().rss / 2**20
28.1796875
>>> wd1 = {x:{i:i for i in d} for x in k}
>>> psutil.Process().memory_info().rss / 2**20
682.78125
>>> del wd1
>>> psutil.Process().memory_info().rss / 2**20
186.21484375

【问题讨论】:

  • 您无法控制 python(或任何其他具有自动或半自动内存管理的现代语言)中的内存管理。
  • 当我们需要在服务器程序上使用python时,这真是一个问题,如何修改python3.5的源代码使其可以在服务器上使用?
  • 只是一个想法,但是使用子进程或多进程模块来完成大块工作呢?一旦 Linux 进程终止,您不会恢复所有内存吗? 如何修改 python3.5 的源代码... 至少对我来说似乎是一个初学者。
  • 哦,您可能还想查看 weakref 看看它是否适用于您的问题。
  • 20GB 对于一些维护内存来说已经足够了。您应该显示获得“不可释放”内存的代码。您可能仍然保留对所有对象的引用。

标签: python python-3.x memory memory-management memory-leaks


【解决方案1】:

一旦你删除了一个对象,它就可以被垃圾回收而不是立即删除 - 所以只要给它一些时间,它就会释放或触发 gc.collect() 以加快处理速度。

python.exe
Python 3.5.1 (v3.5.1:37a07cee5969, Dec  6 2015, 01:38:48) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import psutil
>>> import gc
>>> psutil.Process().memory_info().rss / 2**20
13.2890625
>>> d = {x:x for x in range(10**7)}
>>> psutil.Process().memory_info().rss / 2**20
359.13671875
>>> del d
>>> psutil.Process().memory_info().rss / 2**20
13.5234375
>>> gc.collect()
0
>>> psutil.Process().memory_info().rss / 2**20
13.4375
>>>

仅供参考,Python 3 shell实际上更像ipython 2,其中有一定数量的存储占用历史等,仅供参考:

Python 3.5.1 (v3.5.1:37a07cee5969, Dec  6 2015, 01:38:48) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import psutil
>>> psutil.Process().memory_info().rss / 2**20
13.1875
>>> psutil.Process().memory_info().rss / 2**20
13.20703125
>>> psutil.Process().memory_info().rss / 2**20
13.20703125
>>> psutil.Process().memory_info().rss / 2**20
13.20703125
>>> psutil.Process().memory_info().rss / 2**20
13.20703125
>>> 22*3
66
>>> psutil.Process().memory_info().rss / 2**20
13.25390625
>>> import gc
>>> psutil.Process().memory_info().rss / 2**20
13.25390625
>>> gc.collect()
0
>>> psutil.Process().memory_info().rss / 2**20
13.171875
>>>

第二天早上检查函数中的字典更新是否不同:

>>> psutil.Process().memory_info().rss / 2**20
13.1484375
>>> D = {}
>>> psutil.Process().memory_info().rss / 2**20
13.1484375
>>> def UpdateD(d, v):
...     """ Add the text and value for v to dict d """
...     d[v] = str(v)
...
>>> psutil.Process().memory_info().rss / 2**20
13.16015625
>>> for x in range(10**7):
...     UpdateD(D, x)
...
>>> psutil.Process().memory_info().rss / 2**20
666.6328125
>>> del D
>>> psutil.Process().memory_info().rss / 2**20
10.765625
>>> gc.collect()
0
>>> psutil.Process().memory_info().rss / 2**20
12.8984375
>>>

所以看起来您的生产代码可能会挂在您仍然需要追踪的引用上。

【讨论】:

  • 作为对不熟悉 gc 的人的说明,它会暂时阻塞,所以绝对不是在时间敏感逻辑中间调用的东西。
  • 等了30分钟,又跑了几次gc.collect(),还是显示15.5859375, not freed
  • 同样的事情发生在服务器进程中,不仅仅是在 python3 shell 上,不可释放且不可 gc 收集
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-25
  • 1970-01-01
  • 1970-01-01
  • 2017-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多