python内存泄露的诊断(转)
本篇文章非原创,转载自:http://rstevens.iteye.com/blog/828565 。
对于一个用 python 实现的,长期运行的后台服务进程来说,如果内存持续增长,那么很可能是有了“内存泄露”。
最近在我的项目中,就出现了内存持续增长的情况,google 了一下,发现 Tracing Python memory leaks 讲了一种诊断方式,并给出了实例。而我的案例与此文稍有不同,下面就结合我的案例,谈谈如何诊断内存泄露:
一、内存泄露的原因
对于 python 这种支持垃圾回收的语言来说,怎么还会有内存泄露? 概括来说,有以下三种原因:
1、 所用到的用 C 语言开发的底层模块中出现了内存泄露。
2、 代码中用到了全局的 list、 dict 或其它容器,不停的往这些容器中插入对象,而忘记了在使用完之后进行删除回收
3、 代码中有“引用循环”, python 垃圾处理机制无法进行回收
二、 内存泄露的诊断思路
无论是哪种方式的内存泄露,最终表现的形式都是某些 python 对象在不停的增长;因此,首先是要找到这些异常的对象。
三、 内存泄露的诊断步骤
用到的工具: gc 模块和 objgraph 模块
objgraph 是一个用于诊断内存问题的有用的工具
1、 在服务程序的循环逻辑中,选择出一个诊断点
2、 在诊断点,插入如下诊断语句
import gc
import objgraph
### 强制进行垃圾回收
gc.collect()
### 打印出对象数目最多的 50 个类型信息
objgraph.show_most_common_types(limit=50)
3、 检查统计信息,找到异常对象。
运行加入诊断语句的服务程序,并将打印到屏幕上的统计信息重定向到日志中。运行一段时间后,就可以来分析日志,看看哪些对象在不停的增长。
以我的程序为例,我将日志记录到 log.txt 中,运行一段时间后,发现 tuple 和 list 类型的对象不停增长:
# grep "^list " log.txt
# grep "^tuple " log.txt
如果不停增长的对象,是一些非通用的类型(例如你自己实现的一个 class),那么问题就比较好定位,例如Tracing Python memory leaks中提到的案例。
而对 tuple 和 list 这类通用类型,要想知道对象到底是什么,泄露发生在哪里,还得想点办法。我采用了排查的方式。由于程序的模块化还不错,可以每次禁用一个模块,然后重新跑程序,重新检查日志,看看 tuple 和 list 是否仍然不停增长。这样,很快就能将故障定位到具体的模块中。
最后终于找到了原因,属于上面总结的第二种原因:
我的程序是一个多线程程序,多个线程作为生产者,一个线程作为消费者,通过将一个 tuple 对象送入异步队列进行通信。由于消费者的处理速度跟不上生产者的速度,又没有进行同步, 导致异步队列中的对象越来越多。
四、参考文档
1. http://www.lshift.net/blog/2008/11/14/tracing-python-memory-leaks
2. http://mg.pov.lt/blog/python-object-graphs.html
3. http://mg.pov.lt/blog/hunting-python-memleaks
python内存泄露的诊断(转)的更多相关文章
- python 内存泄露的诊断 - 独立思考 - ITeye技术网站
python 内存泄露的诊断 - 独立思考 - ITeye技术网站 python 内存泄露的诊断 博客分类: 编程语言: Python Python多线程Blog.net 对于一个用 python ...
- python 内存泄露的诊断
对于一个用 python 实现的,长期运行的后台服务进程来说,如果内存持续增长,那么很可能是有了"内存泄露" 一.内存泄露的原因 对于 python 这种支持垃圾回收的语言来说,怎 ...
- 记一次调试python内存泄露的问题
转载:http://www.jianshu.com/p/2d06a1a01cc3 这两天由于公司需要, 自己编写了一个用于接收dicom文件(医学图像文件)的server. 经过各种coding-de ...
- 排查python内存泄露中几个工具的使用
本文主要介绍3个工具:pdb,objgraph,以及pympler. 1.pdb pdb是专门用于python代码调试,模仿gdb. 使用pdb可以查看堆栈,打印变量等. 这里介绍的是命令行下的pdb ...
- 关于排查python内存泄露的简单总结
这次的内存泄露问题是发生在多线程场景下的. 各种工具都试过了,gc,objgraph, pdb,pympler等,仍然没有找到问题所在. pdb感觉用起来很方便,可以调试代码,对原来的代码无侵入性. ...
- python内存泄露memory leak排查记录
问题描述 A服务,是一个检测MGR集群主节点是否发生变化的服务,使用python语言实现的. 针对每个集群,主线程会创建一个子线程,并由子线程去检测.子线程会频繁的创建和销毁. 上线以后,由于经常会有 ...
- 使用gc、objgraph干掉python内存泄露与循环引用!
Python使用引用计数和垃圾回收来做内存管理,前面也写过一遍文章<Python内存优化>,介绍了在python中,如何profile内存使用情况,并做出相应的优化.本文介绍两个更致命的问 ...
- python内存泄露诊断过程记录pyrasite
工具:pyrasite;包含三个命令行 pyrasite / pyrasite-shell / pyrasite-memory-viewer 安装:gdb meliae urwid 说明:Pyrasi ...
- python内存泄露查找
1 前言: 1.1 像Java程序一样,虽然Python本身也有垃圾回收的功能,但是同样也会产生内存泄漏的问题 1.2 在Python程序里,内存泄漏是由于一个长期持有的对象不断的往一个dict或者l ...
随机推荐
- 自签名配置HTTPS
基于AFN3.0 1.将后台提供的.cer文件文件保存至本地 2.在封装的网络请求工具类中为AFN的AFSecurityPolicy属性赋值 -(AFSecurityPolicy *)customSe ...
- EIP权限工作流平台总结-2前端框架
1.预览地址:www.eipflow.com (1) 权限工作流:www.demo.eipflow.com/Account/Login (2) 基础权限版:www.auth.eipflow.com ...
- surging+EFCore 服务实现入门
准备工作 本篇文章基于上篇基础上进行的,请先了解此篇 surging+CentOS7+docker+rancher2.0 菜鸟部署运行笔记 开发环境 Visual Studio 2017 15.5 ...
- opesntack基础知识-软件包历史脉络
软件包管理 软件包管理是每个OpenStack项目的基础,其目的是用来将项目代码打包成源码包或者二进制包进行分发.一个项目的代码可能会被打包放到PyPI上,这样你可以通过pip命令安装这个包:也可能会 ...
- 读《JavaScript权威指南》笔记(一)
1.Number() parseInt() parseFloat() 如果通过Number()转换函数传入一个字符串,它会试图将其转换为一个整数或浮点数直接量,这个方法只能基于十进制数进行转换,并 ...
- ElasticSearch 学习一: 基本命令
1. 启动时指定集群和节点的名字./elasticsearch -Ecluster.name=my_cluster_name -Enode.name=my_node_namee.g. ./elasti ...
- [Xcode 实际操作]五、使用表格-(1)使用UITableView制作简单表格
目录:[Swift]Xcode实际操作 本文将演示表格视图的使用方法. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit //首先添加两个协 ...
- 关于双端队列 deque 模板 && 滑动窗口 (自出)
嗯... deque 即为双端队列,是c++语言中STL库中提供的一个东西,其功能比队列更强大,可以从队列的头与尾进行操作... 但是它的操作与队列十分相似,详见代码1: 1 #include < ...
- mariadb yum安装
安装 yum install mariadb mariadb-server -y 启动 systemctl start mariadb systemctl enable mariadb 安全安装 # ...
- POJ3696 The Luckiest Number 欧拉定理
昨天终于把欧拉定理的证明看明白了...于是兴冲冲地写了2道题,发现自己啥都不会qwq 题意:给定一个正整数L<=2E+9,求至少多少个8连在一起组成正整数是L的倍数. 这很有意思么... 首先, ...