如何释放Python占用的内存

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何释放Python占用的内存相关的知识,希望对你有一定的参考价值。

在上文的优化中,对每500个用户,会进行一些计算并记录结果在磁盘文件中。原本以为这么做,这些结果就在磁盘文件中了,而不会再继续占用内存;但实际上,python的大坑就是Python不会自动清理这些内存。这是由其本身实现决定的。具体原因网上多有文章介绍,这里就不copy了。
本篇博客将贴一个笔者的实验脚本,用以说明Python确实存在这么一个不释放内存的现象,另外也提出一个解决方案,即:先del,再显式调用gc.collect(). 脚本和具体效果见下。

实验环境一:Win 7, Python 2.7

[python] view plain copy
from time import sleep, time
import gc

def mem(way=1):
print time()
for i in range(10000000):
if way == 1:
pass
else: # way 2, 3
del i

print time()
if way == 1 or way == 2:
pass
else: # way 3
gc.collect()
print time()

if __name__ == "__main__":
print "Test way 1: just pass"
mem(way=1)
sleep(20)
print "Test way 2: just del"
mem(way=2)
sleep(20)
print "Test way 3: del, and then gc.collect()"
mem(way=3)
sleep(20)

运行结果如下:

[plain] view plain copy
Test way 1: just pass
1426688589.47
1426688590.25
1426688590.25
Test way 2: just del
1426688610.25
1426688611.05
1426688611.05
Test way 3: del, and then gc.collect()
1426688631.05
1426688631.85
1426688631.95

对于way 1和way 2,结果是完全一样的,程序内存消耗峰值是326772KB,在sleep 20秒时,内存实时消耗是244820KB;
对于way 3,程序内存消耗峰值同上,但是sleep时内存实时消耗就只有6336KB了。

实验环境二: Ubuntu 14.10, Python 2.7.3

运行结果:

[plain] view plain copy
Test way 1: just pass
1426689577.46
1426689579.41
1426689579.41
Test way 2: just del
1426689599.43
1426689601.1
1426689601.1
Test way 3: del, and then gc.collect()
1426689621.12
1426689622.8
1426689623.11

[plain] view plain copy
ubuntu@my_machine:~$ ps -aux | grep test_mem
Warning: bad ps syntax, perhaps a bogus '-'? See
ubuntu 9122 10.0 6.0 270916 245564 pts/1 S+ 14:39 0:03 python test_mem.py
ubuntu 9134 0.0 0.0 8104 924 pts/2 S+ 14:40 0:00 grep --color=auto test_mem
ubuntu@my_machine:~$ ps -aux | grep test_mem
Warning: bad ps syntax, perhaps a bogus '-'? See
ubuntu 9122 10.0 6.0 270916 245564 pts/1 S+ 14:39 0:03 python test_mem.py
ubuntu 9134 0.0 0.0 8104 924 pts/2 S+ 14:40 0:00 grep --color=auto test_mem
ubuntu@my_machine:~$ ps -aux | grep test_mem
Warning: bad ps syntax, perhaps a bogus '-'? See
ubuntu 9122 11.6 0.1 30956 5608 pts/1 S+ 14:39 0:05 python test_mem.py

结论:
以上说明,当调用del时,其实Python并不会真正release内存,而是将其继续放在其内存池中;只有在显式调用gc.collect()时,才会真正release内存。

进一步:
其实回到上一篇博客的脚本中,也让其引入gc.collect(),然后写个监控脚本监测内存消耗情况:

[plain] view plain copy
while ((1)); do ps -aux | sort -n -k5,6 | grep my_script; free; sleep 5; done

结果发现:内存并不会在每500个用户一组执行完后恢复,而是一直持续消耗到仅存约70MB时,gc才好像起作用。本环境中,机器使用的是Cloud instance,总内存2G,可用内存约为1G,本脚本内存常用消耗是900M - 1G。换句话说,对于这个脚本来说,gc并没有立即起作用,而是在系统可用内存从1 - 1.2G下降到只剩70M左右时,gc才开始发挥作用。这点确实比较奇怪,不知道和该脚本是在Thread中使用的gc.collect()是否有关,或者是gc发挥作用原本就不是可控的。笔者尚未做相关实验,可能在下篇博客中继续探讨。

但是,可以肯定的是,若不使用gc.collect(), 原脚本将会将系统内存耗尽而被杀死。这一点从syslog中可以明显看出。
参考技术A 这是关于Python的垃圾回收机制的问题。Python用了引用计数的方法,每有一个指针引用了一个变量,计数就+1,取消引用则-1。当某块变量的引用计数为0时,它就自动地被回收了。

buff/cache占用太多内存,如何释放内存?

buff/cache占用太多内存,如何释放内存?

一、查看free内存

  根据free -h命令,可以看到内存共有7.6G用了623M,但是free只有2.7G。通过观察可以发现buff/cache占用了4.3G。 buff/cache是由于系统读写导致的文件缓存,没有及时释放。

[root@zxy_master ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:           7.6G        623M        2.7G         15M        4.3G        6.7G
Swap:            0B          0B          0B

二、buff/cache

buff是Buffer Cache,即缓冲区缓存。主要是针对块设备的缓存。

cache是Page Cache,即页面缓存。主要用来作为文件系统上的文件数据的缓存来用,尤其是针对当进程对文件read/write操作的时候。

Linux缓存回收机制是,Linux内核会在内存将要耗尽的时候,触发内存回收的工作,以便释放出内存给进程是哟个。一般情况下,释放的这部分内存都是来自于buff/cache部分。

三、手动释放buff/cache

# 清除页面缓存
[root@zxy_master ~]# echo 1 > /proc/sys/vm/drop_caches
# 清除回收slab分配中的对象(包括目录项和inode缓存)
[root@zxy_master ~]# echo 2 > /proc/sys/vm/drop_caches
# 清除页面缓存和slab分配中
[root@zxy_master ~]# echo 3 > /proc/sys/vm/drop_caches
# 释放后内存,可以看到现在可用内存有6.9G
[root@zxy_master ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:           7.6G        627M        6.9G         15M        121M        6.8G
Swap:            0B          0B          0B

以上是关于如何释放Python占用的内存的主要内容,如果未能解决你的问题,请参考以下文章

python中如何释放字典的内存占用?

如何释放Python占用的内存

buff/cache占用太多内存,如何释放内存?

如何释放队列(STL)占用的内存?

创建 matplotlib 图形后如何释放内存

sql 2008 R2 怎样 释放内存