谈谈如何手动释放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实现把数字转换成中文
Jun 29 Python
在阿里云服务器上配置CentOS+Nginx+Python+Flask环境
Jun 18 Python
Python 含参构造函数实例详解
May 25 Python
Python进阶之递归函数的用法及其示例
Jan 31 Python
python 使用socket传输图片视频等文件的实现方式
Aug 07 Python
解决Python计算矩阵乘向量,矩阵乘实数的一些小错误
Aug 26 Python
Python shutil模块用法实例分析
Oct 02 Python
python 实现从高分辨图像上抠取图像块
Jan 02 Python
Python打印特殊符号及对应编码解析
May 07 Python
Django 解决distinct无法去除重复数据的问题
May 20 Python
浅谈优化Django ORM中的性能问题
Jul 09 Python
python 爬取华为应用市场评论
May 29 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
JavaScript高级程序设计(第3版)学习笔记11 内建js对象
2012/10/11 Javascript
jquery自定义类似$.ajax()的方法实现代码
2013/08/13 Javascript
jquery获取checkbox的值并post提交
2015/01/14 Javascript
JavaScript中Date.toSource()方法的使用教程
2015/06/12 Javascript
DataTables+BootStrap组合使用Ajax来获取数据并且动态加载dom的方法(排序,过滤,分页等)
2016/11/09 Javascript
微信小程序 POST请求(网络请求)详解及实例代码
2016/11/16 Javascript
详解nodejs中exports和module.exports的区别
2017/02/17 NodeJs
微信小程序 登录的简单实现
2017/04/19 Javascript
基于jQuery实现图片推拉门动画效果的两种方法
2017/08/26 jQuery
微信小程序实现登录遮罩效果
2018/11/01 Javascript
JS高阶函数原理与用法实例分析
2019/01/15 Javascript
JavaScript实现的滚动公告特效【基于jQuery】
2019/07/10 jQuery
微信自定义分享链接信息(标题,图片和内容)实现过程详解
2019/09/04 Javascript
[43:53]OG vs EG 2019国际邀请赛淘汰赛 胜者组 BO3 第三场 8.22
2019/09/05 DOTA
Python远程桌面协议RDPY安装使用介绍
2015/04/15 Python
Python环境下安装使用异步任务队列包Celery的基础教程
2016/05/07 Python
小白如何入门Python? 制作一个网站为例
2018/03/06 Python
python删除某个字符
2018/03/19 Python
Python解析、提取url关键字的实例详解
2018/12/17 Python
python tkinter窗口最大化的实现
2019/07/15 Python
Python 生成一个从0到n个数字的列表4种方法小结
2019/11/28 Python
使用python计算三角形的斜边例子
2020/04/15 Python
详解CSS的border边框属性及其在CSS3中的新特性
2016/05/10 HTML / CSS
巴基斯坦电子产品购物网站:Home Shopping
2017/09/14 全球购物
俄罗斯香水和化妆品购物网站:Л’Этуаль
2018/05/10 全球购物
Nebula美国官网:便携式投影仪
2019/03/15 全球购物
Ref与out有什么不同
2012/11/24 面试题
J2EE包括哪些技术
2016/11/25 面试题
酒店司机岗位职责
2013/12/14 职场文书
女儿十岁生日答谢词
2014/01/27 职场文书
企业内控岗位的职责
2014/02/07 职场文书
运动会加油口号
2014/06/07 职场文书
赵氏孤儿观后感
2015/06/09 职场文书
2015年重阳节主持词
2015/07/04 职场文书
详细总结Python常见的安全问题
2021/05/21 Python
win11电脑关机鼠标灯还亮怎么解决? win11关机后鼠标灯还亮解决方法
2023/01/09 数码科技