谈谈如何手动释放Python的内存


Posted in Python onDecember 17, 2016

在上篇博客中,提到了对一个脚本进行的多次优化。当时以为已经优化得差不多了,但是当测试人员测试时,我才发现,踩到了Python的一个大坑。

在上文的优化中,对每500个用户,会进行一些计算并记录结果在磁盘文件中。原本以为这么做,这些结果就在磁盘文件中了,而不会再继续占用内存;但实际上,Python的大坑就是Python不会自动清理这些内存。这是由其本身实现决定的。具体原因网上多有文章介绍,这里就不copy了。

本篇博客将贴一个笔者的实验脚本,用以说明Python确实存在这么一个不释放内存的现象,另外也提出一个解决方案,即:先del,再显式调用gc.collect(). 脚本和具体效果见下。

实验环境一:Win 7, Python 2.7

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)

运行结果如下:

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

运行结果:

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
ubuntu@my_machine:~$ ps -aux | grep test_mem 
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html 
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 http://procps.sf.net/faq.html 
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 http://procps.sf.net/faq.html 
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(),然后写个监控脚本监测内存消耗情况:

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中可以明显看出。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python sys.path详细介绍
Oct 17 Python
python有证书的加密解密实现方法
Nov 19 Python
python实现在每个独立进程中运行一个函数的方法
Apr 23 Python
python 使用poster模块进行http方式的文件传输到服务器的方法
Jan 15 Python
python实现从本地摄像头和网络摄像头截取图片功能
Jul 11 Python
Python shelve模块实现解析
Aug 28 Python
python中time库的实例使用方法
Oct 31 Python
python next()和iter()函数原理解析
Feb 07 Python
python实现五子棋程序
Apr 24 Python
Python+Dlib+Opencv实现人脸采集并表情判别功能的代码
Jul 01 Python
python 中关于pycharm选择运行环境的问题
Oct 31 Python
PyCharm配置KBEngine快速处理代码提示冲突、配置命令问题
Apr 03 Python
深入理解NumPy简明教程---数组3(组合)
Dec 17 #Python
深入理解NumPy简明教程---数组2
Dec 17 #Python
深入理解NumPy简明教程---数组1
Dec 17 #Python
Python脚本获取操作系统版本信息
Dec 17 #Python
详解python中xlrd包的安装与处理Excel表格
Dec 16 #Python
详解python开发环境搭建
Dec 16 #Python
python制作爬虫爬取京东商品评论教程
Dec 16 #Python
You might like
实现分十页分向前十页向后十页的处理
2006/10/09 PHP
仿Aspnetpager的一个PHP分页类代码 附源码下载
2012/10/08 PHP
Laravel使用scout集成elasticsearch做全文搜索的实现方法
2018/11/30 PHP
PHP PDOStatement::bindValue讲解
2019/01/30 PHP
在JS中解析HTML字符串示例代码
2014/04/16 Javascript
javascript获取本机操作系统类型的方法
2015/08/13 Javascript
jQuery左侧大图右侧小图焦点图幻灯切换代码分享
2015/08/19 Javascript
js实现的奥运倒计时时钟效果代码
2015/12/09 Javascript
jQuery实现获取table表格第一列值的方法
2016/03/01 Javascript
前端面试知识点锦集(JavaScript篇)
2016/12/28 Javascript
jQuery 利用ztree实现树形表格的实例代码
2017/09/27 jQuery
基于小程序请求接口wx.request封装的类axios请求
2020/07/02 Javascript
解决ant-design-vue中menu菜单无法默认展开的问题
2020/10/31 Javascript
Python set集合类型操作总结
2014/11/07 Python
python中set常用操作汇总
2016/06/30 Python
利用python批量给云主机配置安全组的方法教程
2017/06/21 Python
让Python更加充分的使用Sqlite3
2017/12/11 Python
python自动截取需要区域,进行图像识别的方法
2018/05/17 Python
python得到一个excel的全部sheet标签值方法
2018/12/10 Python
Python实现将多个空格换为一个空格.md的方法
2018/12/20 Python
python tkinter控件布局项目实例
2019/11/04 Python
Python3实现发送邮件和发送短信验证码功能
2020/01/07 Python
python使用梯度下降和牛顿法寻找Rosenbrock函数最小值实例
2020/04/02 Python
使用Python内置模块与函数进行不同进制的数的转换
2020/04/26 Python
python线程池如何使用
2020/05/28 Python
PyCharm 2020.2.2 x64 下载并安装的详细教程
2020/10/15 Python
英格兰足协官方商店:England Store
2019/07/12 全球购物
毕业生文员求职信
2013/11/03 职场文书
八项规定整改措施
2014/02/12 职场文书
上班玩手机检讨书
2014/02/17 职场文书
春节联欢会主持词
2014/03/24 职场文书
化工专业求职信
2014/07/01 职场文书
干部作风整顿自我剖析材料和整改措施
2014/09/18 职场文书
2014年青年教师工作总结
2014/12/17 职场文书
初中军训感言
2015/08/01 职场文书
Golang获取List列表元素的四种方式
2022/04/20 Golang