谈谈如何手动释放Python的内存

作者:执假以为真 时间:2023-09-22 13:03:57 

在上篇博客中,提到了对一个脚本进行的多次优化。当时以为已经优化得差不多了,但是当测试人员测试时,我才发现,踩到了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中可以明显看出。

来源:http://blog.csdn.net/nirendao/article/details/44426201

标签:python,释放内存
0
投稿

猜你喜欢

  • Go语言中的函数式编程实践

    2024-02-03 23:06:58
  • Mysql查询日期timestamp格式的数据实现

    2024-01-22 08:59:55
  • 详解python中的装饰器

    2023-02-20 10:33:36
  • Python如何读取相对路径文件

    2023-12-06 17:03:18
  • 一文教你用Pyecharts做交互图表

    2022-11-20 22:33:38
  • CSS编写过程中常见的10个错误

    2008-05-29 12:49:00
  • Python开发的实用计算器完整实例

    2023-07-25 17:11:53
  • Oracle常用命令大全集

    2010-07-21 13:18:00
  • python 实现视频 图像帧提取

    2023-12-30 19:29:40
  • Python rstrip()方法实例详解

    2021-05-16 10:05:40
  • python中kmeans聚类实现代码

    2023-09-27 19:49:44
  • 浅析python中的分片与截断序列

    2022-05-11 02:31:03
  • python脚本框架webpy入门安装及应用创建

    2023-08-23 05:08:51
  • 科讯商业版中用到的ajax空间与分页函数

    2024-04-17 10:05:45
  • Python基础之函数与控制语句

    2021-02-02 16:22:49
  • Python中zip函数如何使用

    2021-03-30 02:54:13
  • python 读取、写入txt文件的示例

    2023-09-29 22:04:18
  • Springboot连接数据库及查询数据完整流程

    2024-01-18 07:25:29
  • Python实现将数据库一键导出为Excel表格的实例

    2024-01-19 19:47:27
  • php使用递归与迭代实现快速排序示例

    2023-11-14 09:46:31
  • asp之家 网络编程 m.aspxhome.com