谈谈如何手动释放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 相关文章推荐
Tensorflow 利用tf.contrib.learn建立输入函数的方法
Feb 08 Python
Python键盘输入转换为列表的实例
Jun 23 Python
Windows下python3.7安装教程
Jul 31 Python
Django框架文件上传与自定义图片上传路径、上传文件名操作分析
May 10 Python
使用celery和Django处理异步任务的流程分析
Feb 19 Python
在Python 的线程中运行协程的方法
Feb 24 Python
Jupyter Notebook输出矢量图实例
Apr 14 Python
pytorch读取图像数据转成opencv格式实例
Jun 02 Python
python中的插入排序的简单用法
Jan 19 Python
pytorch Dropout过拟合的操作
May 27 Python
python中redis包操作数据库的教程
Apr 19 Python
python开发人人对战的五子棋小游戏
May 02 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自定义函数返回多个值
2006/11/26 PHP
比较简单实用的PHP无限分类源码分享(思路不错)
2011/10/13 PHP
php的$_FILES的临时储存文件与回收机制实测过程
2013/07/12 PHP
Codeigniter实现智能裁剪图片的方法
2014/06/12 PHP
Yii2框架使用计划任务的方法
2016/05/25 PHP
AJAX PHP无刷新form表单提交的简单实现(推荐)
2016/09/09 PHP
PHP流Streams、包装器wrapper概念与用法实例详解
2017/11/17 PHP
JQuery 无废话系列教程(一) jquery入门 [推荐]
2009/06/23 Javascript
js简单实现交换Li的值
2014/05/22 Javascript
javascript瀑布流布局实现方法详解
2016/02/17 Javascript
nodejs 的 session 简单使用
2016/06/06 NodeJs
浅谈键盘上回车按钮的js触发事件
2017/02/13 Javascript
微信小程序注册60s倒计时功能 使用JS实现注册60s倒计时功能
2017/08/16 Javascript
详解小程序缓存插件(mrc)
2018/08/17 Javascript
Nodejs把接收图片base64格式保存为文件存储到服务器上
2018/09/26 NodeJs
vue项目使用axios发送请求让ajax请求头部携带cookie的方法
2018/09/26 Javascript
微信小程序搭建自己的Https服务器
2019/05/02 Javascript
jQuery-App输入框实现实时搜索
2020/11/19 jQuery
[48:52]DOTA2上海特级锦标赛A组小组赛#2 Secret VS CDEC第一局
2016/02/25 DOTA
解决Python中字符串和数字拼接报错的方法
2016/10/23 Python
Python基础教程之内置函数locals()和globals()用法分析
2018/03/16 Python
python中pika模块问题的深入探究
2018/10/13 Python
Django ORM 自定义 char 类型字段解析
2019/08/09 Python
Django对models里的objects的使用详解
2019/08/17 Python
Python3的unicode编码转换成中文的问题及解决方案
2019/12/10 Python
Nginx+Uwsgi+Django 项目部署到服务器的思路详解
2020/05/08 Python
使用tensorflow进行音乐类型的分类
2020/08/14 Python
美国批发零售网站:GearXS
2016/07/26 全球购物
马来西亚排名第一的宠物用品店:Pets Wonderland
2020/04/16 全球购物
新电JAVA笔试题目
2014/08/31 面试题
应届生法律顾问求职信
2013/11/19 职场文书
2014年小学元旦活动方案
2014/02/12 职场文书
大学生评语大全
2014/04/18 职场文书
广告学专业毕业生自荐信
2014/05/28 职场文书
加强作风建设心得体会
2014/10/22 职场文书
python实现简易自习室座位预约系统
2021/06/30 Python