谈谈如何手动释放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中对list去重的多种方法
Sep 18 Python
极简的Python入门指引
Apr 01 Python
Python跨文件全局变量的实现方法示例
Dec 10 Python
在Python 2.7即将停止支持时,我们为你带来了一份python 3.x迁移指南
Jan 30 Python
tensorflow实现对图片的读取的示例代码
Feb 12 Python
Python向Excel中插入图片的简单实现方法
Apr 24 Python
Python3删除排序数组中重复项的方法分析
Jan 31 Python
用python画一只可爱的皮卡丘实例
Nov 21 Python
python 项目目录结构设置
Feb 14 Python
基于Python生成个性二维码过程详解
Mar 05 Python
解决django接口无法通过ip进行访问的问题
Mar 27 Python
python 基于卡方值分箱算法的实现示例
Jul 17 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
dedecms中常见问题修改方法总结
2007/03/21 PHP
php的$_FILES的临时储存文件与回收机制实测过程
2013/07/12 PHP
PHP实现支持GET,POST,Multipart/form-data的HTTP请求类
2014/09/24 PHP
php组合排序简单实现方法
2016/10/15 PHP
关于Laravel参数验证的一些疑与惑
2019/11/19 PHP
在jQuery中 常用的选择器介绍
2013/04/16 Javascript
js判断某个方法是否存在实例代码
2015/01/10 Javascript
JQuery动画与特效实例分析
2015/02/02 Javascript
ES6的新特性概览
2016/03/10 Javascript
onclick和onblur冲突问题的快速解决方法
2016/04/28 Javascript
mongoose中利用populate处理嵌套的方法
2017/05/26 Javascript
jQuery实现键盘回车搜索功能
2017/07/25 jQuery
原生js的ajax和解决跨域的jsonp(实例讲解)
2017/10/16 Javascript
关于vue单文件中引用路径的处理方法
2018/01/08 Javascript
Object.keys() 和 Object.getOwnPropertyNames() 的区别详解
2020/05/21 Javascript
vue+animation实现翻页动画
2020/06/29 Javascript
Vue 3.0中jsx语法的使用
2020/11/13 Javascript
[01:09:20]NB vs NAVI Supermajor小组赛A组 BO3 第二场 6.2
2018/06/03 DOTA
python控制台英汉汉英电子词典
2020/04/23 Python
Python NumPy库安装使用笔记
2015/05/18 Python
图解Python变量与赋值
2018/04/03 Python
Python基于Opencv来快速实现人脸识别过程详解(完整版)
2019/07/11 Python
关于Python Tkinter Button控件command传参问题的解决方式
2020/03/04 Python
澳大利亚领先的折扣药房:Chemist Direct(有中文站)
2018/11/24 全球购物
如何使用PHP session
2015/04/21 面试题
销售总监岗位职责
2014/01/04 职场文书
《燕子》教学反思
2014/02/18 职场文书
2014年国培研修感言
2014/03/09 职场文书
合作协议书怎么写
2014/04/18 职场文书
专家推荐信模板
2014/05/09 职场文书
2014年前台接待工作总结
2014/12/05 职场文书
2015年幼儿园班务工作总结
2015/05/12 职场文书
话题作文之生命的旋律
2019/12/17 职场文书
Mysql效率优化定位较低sql的两种方式
2021/05/26 MySQL
python百行代码实现汉服圈图片爬取
2021/11/23 Python
CentOS7环境下MySQL8常用命令小结
2022/06/10 Servers