谈谈如何手动释放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 相关文章推荐
Python3中常用的处理时间和实现定时任务的方法的介绍
Apr 07 Python
PyCharm代码格式调整方法
May 23 Python
python消除序列的重复值并保持顺序不变的实例
Nov 08 Python
对python 自定义协议的方法详解
Feb 13 Python
Python操作excel的方法总结(xlrd、xlwt、openpyxl)
Sep 02 Python
Python中的单下划线和双下划线使用场景详解
Sep 09 Python
python获取全国城市pm2.5、臭氧等空气质量过程解析
Oct 12 Python
Python基于codecs模块实现文件读写案例解析
May 11 Python
Python pandas如何向excel添加数据
May 22 Python
Python趣味实例,实现一个简单的抽奖刮刮卡
Jul 18 Python
Python DataFrame使用drop_duplicates()函数去重(保留重复值,取重复值)
Jul 20 Python
python中time.ctime()实例用法
Feb 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
利用discuz实现PHP大文件上传应用实例代码
2008/11/14 PHP
约瑟夫环问题的PHP实现 使用PHP数组内部指针操作函数
2010/10/12 PHP
thinkphp3.0 模板中函数的使用
2012/11/13 PHP
php命令行用法入门实例教程
2014/10/27 PHP
Cygwin中安装PHP方法步骤
2015/07/04 PHP
Yii中创建自己的Widget实例
2016/01/05 PHP
Symfony2在Nginx下的配置方法图文教程
2016/02/04 PHP
PHP结合Ueditor并修改图片上传路径
2016/10/16 PHP
php 实现Hash表功能实例详解
2016/11/29 PHP
[原创]php实现 data url的图片生成与保存
2016/12/04 PHP
基于PHP实现微信小程序客服消息功能
2019/08/12 PHP
提高网站信任度的技巧
2008/10/17 Javascript
小议javascript 设计模式 推荐
2009/10/28 Javascript
事件绑定之小测试  onclick && addEventListener
2011/07/31 Javascript
JS TextArea字符串长度限制代码集合
2012/10/31 Javascript
jQuery 借助插件Lavalamp实现导航条动态美化效果
2013/09/27 Javascript
jquery cookie的用法总结
2013/11/18 Javascript
TypeError document.getElementById(...) is null错误原因
2015/05/18 Javascript
基于canvas实现的绚丽圆圈效果完整实例
2016/01/26 Javascript
深入理解node.js http模块
2018/01/24 Javascript
对vue.js中this.$emit的深入理解
2018/02/23 Javascript
uni-app微信小程序登录并使用vuex存储登录状态的思路详解
2019/11/04 Javascript
解决node.js含有%百分号时发送get请求时浏览器地址自动编码的问题
2019/11/20 Javascript
javascript-hashchange事件和历史状态管理实例分析
2020/04/18 Javascript
Python selenium根据class定位页面元素的方法
2019/02/26 Python
windows下python虚拟环境virtualenv安装和使用详解
2019/07/16 Python
CSS3实现可翻转的hover效果
2018/05/23 HTML / CSS
加拿大购物频道:The Shopping Channel
2016/07/21 全球购物
幼儿园教师辞职信
2014/01/18 职场文书
党的群众路线教育实践活动总结材料
2014/10/30 职场文书
2016年春节慰问信息
2015/03/25 职场文书
公司财务部岗位职责
2015/04/14 职场文书
运动员入场词
2015/07/18 职场文书
postgresql无序uuid性能测试及对数据库的影响
2021/06/11 PostgreSQL
手写实现JS中的new
2021/11/07 Javascript
Win11怎么启动任务管理器?Win11启动任务管理器的几种方法
2021/11/23 数码科技