问题描述
调试python程序时,用下面这段代码,可以获得进程占用系统内存值。程序跑一段时间后,就能画出进程对内存的占用情况。
def memory_usage_psutil(): # return the memory usage in MB import psutil,os process = psutil.Process(os.getpid()) mem = process.memory_info()[0] / float(2 ** 20) return mem
发现进程的内存占用一直再上涨,而这从逻辑上来说是不正常的,所以想到程序可能发生了Memory Leak。
python程序的Mem Leak
python程序不可能像C/C++一样出现malloc了的内存没有free这样的Memory Leak。但也会遇到“逻辑上没free”的情况,如下代码所示。
def foo(a=[]): a.append(time.time()) return a
参数a这样可迭代的对象,稍不注意,它就能增长的很快。说白了,python的Memory Leak,就是“进程占用的内存莫名其妙一直再升高”。进程占用内存一直升高,与逻辑预期不一致,就可能发生了Memory Leak。
以下面程序为例说明Memory Leak调试的过程:
def memory_usage_psutil(): # return the memory usage in MB import psutil,os process = psutil.Process(os.getpid()) mem = process.memory_info()[0] / float(2 ** 20) return mem def get_current_obj(a=[]): a.append([0]*1000) return a def main(): obj = [] for i in range(10000): obj = get_current_obj(obj) if(i%100==0): print(memory_usage_psutil()) if __name__=='__main__': main()
调试过程
用pmap -x [pid]查看进程占用的堆内存大小
首先想到,会不会是上面用的memory_usage_psutil函数统计错误呢。
先运行程序,再用pmap查看,发现进程内存占用确实很高。多次执行该命令,也可以发现内存一直升高。
强制执行GC(gc.collect())
在需要执行GC的地方加上gc.collect()
def main(): obj = [] for i in range(10000): obj = get_current_obj(obj) import gc;gc.collect() if(i%100==0): print(memory_usage_psutil())
可以看到,强制GC后,程序执行变慢,但内存依然不断升高。
使用memory_profiler查看
安装memory_profiler
pip install -U memory_profiler
用@profile修饰需要查看内存的函数
@profile def main(): obj = [] for i in range(10000): obj = get_current_obj(obj) if(i%100==0): print(memory_usage_psutil())
用如下命令运行程序
python -m memory_profiler main.py
可以看到程序执行完成后,输出结果如下
Line # Mem usage Increment Line Contents ================================================ 12 28.570 MiB 0.000 MiB @profile 13 def main(): 14 28.570 MiB 0.000 MiB obj = [] 15 106.203 MiB 77.633 MiB for i in range(10000): 16 106.203 MiB 0.000 MiB obj = get_current_obj(obj) 17 106.203 MiB 0.000 MiB if(i%100==0): 18 105.445 MiB -0.758 MiB print(memory_usage_psutil())
这样就能看到导致内存上涨最快的那几行代码。
用guppy查看python对象占用的堆内存大小
将main修改如下,即可查看python对堆内存的占用量。
def main(): obj = [] for i in range(10000): obj = get_current_obj(obj) if(i%100==0): print(memory_usage_psutil()) from guppy import hpy;hxx = hpy();heap = hxx.heap() print(heap)
下面就是输出结果,python程序中各个对象对内存的占用从大到小排列。
Index Count % Size % Cumulative % Kind (class / dict of class) 0 10124 22 81944416 95 81944416 95 list 1 16056 34 1325464 2 83269880 96 str 2 9147 20 745616 1 84015496 97 tuple 3 102 0 366480 0 84381976 98 dict of module 4 287 1 313448 0 84695424 98 dict of type 5 2426 5 310528 0 85005952 98 types.CodeType 6 2364 5 283680 0 85289632 99 function 7 287 1 256960 0 85546592 99 type 8 169 0 192088 0 85738680 99 dict (no owner) 9 123 0 142728 0 85881408 99 dict of class
可以从结果中看到,95%的进程内存,都被一个list占用。
还可以通过下面这种方式,查看这个占内存最大的list中的数据类型。
from guppy import hpy;hxx = hpy();byrcs = hxx.heap().byrcs; byrcs[0].byid
关于guppy的详细用法,可以看这里(http://smira.ru/wp-content/uploads/2011/08/heapy.html)。
以上这篇对python程序内存泄漏调试的记录就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
python,内存泄漏,调试
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。
更新日志
- 雨林唱片《赏》新曲+精选集SACD版[ISO][2.3G]
- 罗大佑与OK男女合唱团.1995-再会吧!素兰【音乐工厂】【WAV+CUE】
- 草蜢.1993-宝贝对不起(国)【宝丽金】【WAV+CUE】
- 杨培安.2009-抒·情(EP)【擎天娱乐】【WAV+CUE】
- 周慧敏《EndlessDream》[WAV+CUE]
- 彭芳《纯色角3》2007[WAV+CUE]
- 江志丰2008-今生为你[豪记][WAV+CUE]
- 罗大佑1994《恋曲2000》音乐工厂[WAV+CUE][1G]
- 群星《一首歌一个故事》赵英俊某些作品重唱企划[FLAC分轨][1G]
- 群星《网易云英文歌曲播放量TOP100》[MP3][1G]
- 方大同.2024-梦想家TheDreamer【赋音乐】【FLAC分轨】
- 李慧珍.2007-爱死了【华谊兄弟】【WAV+CUE】
- 王大文.2019-国际太空站【环球】【FLAC分轨】
- 群星《2022超好听的十倍音质网络歌曲(163)》U盘音乐[WAV分轨][1.1G]
- 童丽《啼笑姻缘》头版限量编号24K金碟[低速原抓WAV+CUE][1.1G]