谈谈如何手动释放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编写的com组件发生R6034错误的原因与解决办法
Apr 01 Python
python解析文件示例
Jan 23 Python
Python最长公共子串算法实例
Mar 07 Python
Python与人工神经网络:使用神经网络识别手写图像介绍
Dec 19 Python
Python实现将json文件中向量写入Excel的方法
Mar 26 Python
python实现简单的文字识别
Nov 27 Python
记录Python脚本的运行日志的方法
Jun 05 Python
pyecharts绘制中国2020肺炎疫情地图的实例代码
Feb 12 Python
ipython jupyter notebook中显示图像和数学公式实例
Apr 15 Python
Python替换NumPy数组中大于某个值的所有元素实例
Jun 08 Python
Appium+Python实现简单的自动化登录测试的实现
Jan 26 Python
Python日志模块logging用法
Jun 05 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实现异步数据调用的方法
2015/12/24 PHP
PHP检测数据类型的几种方法(总结)
2017/03/04 PHP
PHP钩子与简单分发方式实例分析
2017/09/04 PHP
Mootools 1.2教程 类(一)
2009/09/15 Javascript
Jquery实现自定义弹窗示例
2014/03/12 Javascript
一个不错的js html页面倒计时可精确到秒
2014/10/22 Javascript
基于jquery实现左右按钮点击的图片切换效果
2021/01/27 Javascript
关于验证码在IE中不刷新的快速解决方法
2016/09/23 Javascript
javascript代码调试之console.log 用法图文详解
2016/09/30 Javascript
使用jquery.qrcode.js生成二维码插件
2016/10/17 Javascript
原生js简单实现放大镜特效
2017/05/16 Javascript
echarts学习笔记之图表自适应问题详解
2017/11/22 Javascript
js canvas实现红包照片效果
2018/08/21 Javascript
Vue 使用formData方式向后台发送数据的实现
2019/04/14 Javascript
这15个Vue指令,让你的项目开发爽到爆
2019/10/11 Javascript
JavaScript中的各种宽高属性的实现
2020/05/08 Javascript
Python的Django框架中的select_related函数对QuerySet 查询的优化
2015/04/01 Python
Windows下Python的Django框架环境部署及应用编写入门
2016/03/10 Python
flask中过滤器的使用详解
2018/08/01 Python
Django如何使用第三方服务发送电子邮件
2019/08/14 Python
Python+OpenCV 实现图片无损旋转90°且无黑边
2019/12/12 Python
浅谈TensorFlow之稀疏张量表示
2020/06/30 Python
2021年的Python 时间轴和即将推出的功能详解
2020/07/27 Python
Ubuntu 20.04安装Pycharm2020.2及锁定到任务栏的问题(小白级操作)
2020/10/29 Python
5分钟让你掌握css3阴影、倒影、渐变小技巧(小编推荐)
2016/08/15 HTML / CSS
菲律宾酒店预订网站:Hotels.com菲律宾
2017/07/12 全球购物
ghd澳大利亚官方网站:英国最受欢迎的美发工具品牌
2018/05/21 全球购物
《月迹》教学反思
2014/02/19 职场文书
公司承诺书范文
2014/05/19 职场文书
2014领导干部四风问题查摆思想汇报
2014/09/13 职场文书
群众路线对照检查材料思想汇报怎么写
2014/09/18 职场文书
北京英文导游词
2015/02/12 职场文书
我的生日感言
2015/08/03 职场文书
《家庭教育》读后感3篇
2019/12/18 职场文书
Pytorch 如何实现LSTM时间序列预测
2021/05/17 Python
MySQL 8.0 驱动与阿里druid版本兼容问题解决
2021/07/01 MySQL