谈谈如何手动释放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 相关文章推荐
Windows下安装python2和python3多版本教程
Mar 30 Python
python中日志logging模块的性能及多进程详解
Jul 18 Python
Python对数据进行插值和下采样的方法
Jul 03 Python
python实现在遍历列表时,直接对dict元素增加字段的方法
Jan 15 Python
深入了解和应用Python 装饰器 @decorator
Apr 02 Python
用python求一个数组的和与平均值的实现方法
Jun 29 Python
VPS CENTOS 上配置python,mysql,nginx,uwsgi,django的方法详解
Jul 01 Python
Python定时发送天气预报邮件代码实例
Sep 09 Python
tensorflow中tf.slice和tf.gather切片函数的使用
Jan 19 Python
基于python实现地址和经纬度转换
May 19 Python
python如何使用代码运行助手
Jul 03 Python
torchxrayvision包安装过程(附pytorch1.6cpu版安装)
Aug 26 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 win下Socket方式发邮件类
2009/08/21 PHP
Laravel 5框架学习之向视图传送数据
2015/04/08 PHP
PHP利用curl发送HTTP请求的实例代码
2020/07/09 PHP
JS中style属性
2006/10/11 Javascript
javascript 实用的文字链提示框效果
2010/06/30 Javascript
上传文件返回的json数据会被提示下载问题解决方案
2014/12/03 Javascript
理解Javascript的call、apply
2015/12/16 Javascript
bootstrap网页框架的使用方法
2016/05/10 Javascript
关于function类中定义变量this的简单说明
2016/05/28 Javascript
JavaScript数据结构之链表的实现
2017/03/19 Javascript
vue导航栏部分的动态渲染实例
2019/11/01 Javascript
微信小程序实现星级评价
2019/11/20 Javascript
JavaScript装饰者模式原理与用法实例详解
2020/03/09 Javascript
Vue.js中Line第三方登录api的实现代码
2020/06/29 Javascript
vue项目打包为APP,静态资源正常显示,但API请求不到数据的操作
2020/09/12 Javascript
[03:37]2014DOTA2国际邀请赛 主赛事第一日胜者组TOPPLAY
2014/07/19 DOTA
[01:01:29]2018DOTA2亚洲邀请赛 4.4 淘汰赛 VP vs Liquid 第一场
2018/04/05 DOTA
Python使用urllib2模块抓取HTML页面资源的实例分享
2016/05/03 Python
python将ansible配置转为json格式实例代码
2017/05/15 Python
Python实现单词翻译功能
2017/06/06 Python
pyttsx3实现中文文字转语音的方法
2018/12/24 Python
Django 后台获取文件列表 InMemoryUploadedFile的例子
2019/08/07 Python
python设置随机种子实例讲解
2019/09/12 Python
django 框架实现的用户注册、登录、退出功能示例
2019/11/28 Python
python3格式化字符串 f-string的高级用法(推荐)
2020/03/04 Python
Python基于爬虫实现全网搜索并下载音乐
2021/02/14 Python
三只松鼠官方旗舰店:全网坚果销售第1
2017/11/25 全球购物
说出数据连接池的工作机制是什么?
2013/04/19 面试题
棉花姑娘教学反思
2014/02/15 职场文书
购房意向书
2014/04/01 职场文书
高中教师先进事迹材料
2014/08/22 职场文书
预备党员学习十八届三中全会精神思想汇报
2014/09/13 职场文书
入党积极分子培养联系人意见
2015/08/12 职场文书
Go标准容器之Ring的使用说明
2021/05/05 Golang
Python下opencv库的安装过程及问题汇总
2021/06/11 Python
了解Kubernetes中的Service和Endpoint
2022/04/01 Servers