谈谈如何手动释放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使用BeautifulSoup分析网页信息的方法
Apr 04 Python
Python自定义scrapy中间模块避免重复采集的方法
Apr 07 Python
Django如何实现内容缓存示例详解
Sep 24 Python
把csv文件转化为数组及数组的切片方法
Jul 04 Python
win10 64bit下python NLTK安装教程
Sep 19 Python
python3实现多线程聊天室
Dec 12 Python
Python matplotlib通过plt.scatter画空心圆标记出特定的点方法
Dec 13 Python
Python正则匹配判断手机号是否合法的方法
Dec 09 Python
keras读取h5文件load_weights、load代码操作
Jun 12 Python
Python手拉手教你爬取贝壳房源数据的实战教程
May 21 Python
Python类方法总结讲解
Jul 26 Python
Python first-order-model实现让照片动起来
Jun 25 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
PHP clearstatcache()函数详解
2010/03/02 PHP
PHP5中GD库生成图形验证码(有汉字)
2013/07/28 PHP
PHP实现返回JSON和XML的类分享
2015/01/28 PHP
php生成唯一数字id的方法汇总
2015/11/18 PHP
Zend Framework教程之Application用法实例详解
2016/03/14 PHP
功能强大的PHP POST提交数据类
2016/07/15 PHP
js 判断浏览器类型 去全角、半角空格 自动关闭当前窗口
2009/04/10 Javascript
jQuery 技巧大全(新手入门篇)
2009/05/12 Javascript
js闭包实例汇总
2014/11/09 Javascript
JavaScript中连接操作Oracle数据库实例
2015/04/02 Javascript
10条建议帮助你创建更好的jQuery插件
2015/05/18 Javascript
jQuery实现图片轮播特效代码分享
2015/09/15 Javascript
基于jQuery实现的美观星级评论打分组件代码
2015/10/30 Javascript
jquery实现简单文字提示效果
2015/12/02 Javascript
JS实现合并两个数组并去除重复项只留一个的方法
2015/12/17 Javascript
适用于javascript开发者的Processing.js入门教程
2016/02/24 Javascript
jQuery基本筛选选择器实例代码
2017/02/06 Javascript
javascript浏览器用户代理检测脚本实现方法
2017/10/27 Javascript
微信小程序实现动态获取元素宽高的方法分析
2018/12/10 Javascript
vue中格式化时间过滤器代码实例
2019/04/17 Javascript
Element Dropdown下拉菜单的使用方法
2020/07/26 Javascript
详解微信小程序轨迹回放实现及遇到的坑
2021/02/02 Javascript
Python完成毫秒级抢淘宝大单功能
2019/06/06 Python
Python+OpenCV实现实时眼动追踪的示例代码
2019/11/11 Python
将python依赖包打包成window下可执行文件bat方式
2019/12/26 Python
Python+OpenCV图像处理——实现直线检测
2020/10/23 Python
关于Python 解决Python3.9 pandas.read_excel(‘xxx.xlsx‘)报错的问题
2020/11/28 Python
基于html和CSS3制作酷炫的导航栏
2015/09/23 HTML / CSS
牦牛毛户外探险服装:Kora
2019/02/08 全球购物
测控技术自荐信
2014/06/05 职场文书
隐形的翅膀观后感
2015/06/10 职场文书
房屋所有权证明
2015/06/19 职场文书
朋友聚会祝酒词
2015/08/10 职场文书
《日月潭》教学反思
2016/02/20 职场文书
关于python3 opencv 图像二值化的问题(cv2.adaptiveThreshold函数)
2022/04/04 Python