关于 python 内存释放问题的一个疑惑

2016-07-30 08:34:57 +08:00
 SlipStupig

python 刚运行时只占用 3M 内存

清单 1 :

mt = {}
for i in xrange(10000000):
    mt.setdefualt(i, i)

这么时候我机器占用了 450MB 内存

然后我执行: del mt
内存占用 230MB,内存再也不是刚开始执行时候的 3MB 了,这个是为什么呢?

4972 次点击
所在节点    Python
15 条回复
lll9p
2016-07-30 08:53:37 +08:00
试试

import gc

gc.collect()
SErHo
2016-07-30 08:54:02 +08:00
大部分的 malloc 实现和 Python 的对象分配都有用内存池, Python 对象回收不一定会调用 free ,即使调用 free 一些 malloc 实现也不会将内存还给操作系统。
SlipStupig
2016-07-30 09:22:13 +08:00
@lll9p GC 对象返回的是 0 哦
sujin190
2016-07-30 10:09:21 +08:00
整数缓存,每个整个只分配一次内存,但一旦分配了内存一般是不回收的,即使不使用了
aec4d
2016-07-30 10:14:35 +08:00
http://stackoverflow.com/questions/1316767/how-can-i-explicitly-free-memory-in-python
我比较喜欢这个回答 http://effbot.org/pyfaq/why-doesnt-python-release-the-memory-when-i-delete-a-large-object.htm
It ’ s that you ’ ve created 5 million integers simultaneously alive, and each int object consumes 12 bytes. “ For speed ”, Python maintains an internal free list for integer objects. Unfortunately, that free list is both immortal and unbounded in size. floats also use an immortal & unbounded free list.

邮件列表
https://mail.python.org/pipermail/python-bugs-list/2004-October/025619.html

意思就是 python 内部为了速度有一个整数缓存列表,添加了进去之后不知道怎么删除。。。。
wangxn
2016-07-30 10:16:23 +08:00
学习了。 Python 的 GC 大部分时候都工作得很好。
SlipStupig
2016-07-30 10:49:32 +08:00
@sujin190 你这么说还是有问题,为什么我删除了对象后内存少了很多,我再次跑清单 1 的时候,内存又变多了
sujin190
2016-07-30 12:11:15 +08:00
@SlipStupig dict 对象不是还要占内存么?你删除了 dict 对象内存当然会释放一部分了
SlipStupig
2016-07-30 12:18:40 +08:00
@sujin190 对象开始申请没占用那么大,删除后占用就变大了? 而且你说的是缓存啊,就是内存的数据应该还是存在的啊,为什么我继续添加整形数据的时候又变大了呢?(执行一样的语句)
ruoyu0088
2016-07-30 12:38:22 +08:00
Python3 解决了这个问题。
lll9p
2016-07-30 12:41:13 +08:00
@SlipStupig @ruoyu0088 原来是版本不一样
GeekGao
2016-07-30 17:21:03 +08:00
这里涉及到整数对象池概念:
python 的 VM 实现中,有大整数和小整数对象池的概念。
首次使用大整数(>257 )时会分配大量内存块, PyIntObject 对象被销毁时,它所占有的内存并不会被释放,归还给系统,而是继续被 Python 保留着
GeekGao
2016-07-30 17:24:28 +08:00
对象池不是复用那些整数们,而是为了复用占据的内存空间,避免频繁创建和释放带来很大的性能开销
zxc111
2016-07-30 19:48:14 +08:00
GeekGao
2016-07-31 00:26:25 +08:00
@zxc111 这种方法很讨巧, Python multiprocessing 模块 fork 一个 child process 开销很大的,估摸至少十几个到几十个 us 的时间就没了,如果是在 linux 平台可以使用 vfork 撸一个进程出来,降低 os.fork 调用的开销,让 child process 计算部分先行

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/295938

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX