您好,登录后才能下订单哦!
这篇文章将为大家详细讲解有关python中如何解决内存泄漏问题,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
其实这次主要是在使用aiohttp写一个接口的时候出现的问题,其实复现出问题非常容易,我们实现一个简单的接受post请求接口的服务端,然后实现一个并发的客户端来访问这个接口,来查看内存的情况
注意: 这个问题是在一个包的特定版本出现的:multidict==4.5.1,
我在整理这个文章2个小时前作者已经修复了这个问题发布了4.5.2版本,已经修复了内存的问题,并且我也进行了测试验证
服务端代码:
from aiohttp import web async def hello(request): return web.json_response(await request.json()) app = web.Application() app.add_routes([web.post('/', hello)]) web.run_app(app)
客户端代码:
import asyncio import aiohttp async def foo(times): data = {'foo': 1} async with aiohttp.ClientSession() as session: for x in range(times): resp = await session.post('http://localhost:8080', json=data) if not x % 100: print(await resp.json()) loop = asyncio.get_event_loop() loop.run_until_complete(foo(100000)) loop.close()
因为我的代码是在linux上跑的,或者mac上我们都可以通过htop非常方面的实时查看我们程序内存的占用情况,我们先将服务端启动,查看一下我们此时的内存情况可以看到占用的
非常少,当我们打开客户端之后,再次观察我们可以看到内存不断增长,及时我们客户端运行完毕内存也不会降低。
当客户端结束之后的内存:
如果客户端不停止的话内存会一直涨,最后的结果就是把你的系统内存吃完,然后被系统杀掉你的进程。
像上面的例子是一个非常简单的程序,不复杂我们也并没有做上面复杂的操作就是一个简单的接受post请求的服务端,但是如果是在实际的项目中我们可能会写非常复杂的业务逻辑,那到时候我们又如何找到是哪里导致的内存问题,当我碰到这个问题的时候,其实我和很多接触python不久的人差不多,也是不知道怎么查这种问题,各种百度各种查,也找到了好多推荐的工具,memory_profiler库,objgraph库,graphviz工具,但是都没有帮助我迅速的找到问题点在哪里,最后看到标准库中的tracemalloc,地址:https://docs.python.org/3/library/tracemalloc.html
通过这个包很快帮我找到了内存泄漏的地方
接下来按照官网的方法我将代码进行改写,来测试到底哪里的问题导致的内存泄漏,更改后的服务端代码为:
from aiohttp import web import tracemalloc async def hello(request): return web.json_response(await request.json()) async def get_info(request): snapshot2 = tracemalloc.take_snapshot() top_stats = snapshot2.compare_to(snapshot1, 'lineno') print(top_stats) return web.Response(text="ok") if __name__ == '__main__': app = web.Application() app.add_routes( [ web.post('/', hello), web.get("/get_info", get_info) ] ) tracemalloc.start() snapshot1 = tracemalloc.take_snapshot() web.run_app(app)
注意print(top_stats)这行打印的结果最后要关注
其实这里就是新增加了一个路由get_info, 我们启动服务端之后开启客户端,当我们客户端运行完毕之后,可以看到内存已经涨上去了,并且没有不会释放,这个时候,可以直接通过浏览器访问get_info这个路由看看print打印的内容,这里将会打印出你程序运行到这个时候那一行的代码内存增长的比较多,进行一次排序,前面的几个其实都是需要你关注的,因为这里数据较多,我就只打印如下前几个数据
<StatisticDiff traceback=<Traceback (<Frame filename='/Users/zhaofan/anaconda3/lib/python3.6/site-packages/aiohttp/web_response.py' lineno=56>,)> size=116500672 (+116500672) count=300004 (+300004)>, <StatisticDiff traceback=<Traceback (<Frame filename='/Users/zhaofan/anaconda3/lib/python3.6/site-packages/aiohttp/web_response.py' lineno=604>,)> size=11400000 (+11400000) count=200000 (+200000)>, <StatisticDiff traceback=<Traceback (<Frame filename='/Users/zhaofan/anaconda3/lib/python3.6/site-packages/aiohttp/web_response.py' lineno=472>,)> size=8000000 (+8000000) count=100000 (+100000)>, <StatisticDiff traceback=<Traceback (<Frame filename='/Users/zhaofan/anaconda3/lib/python3.6/site-packages/aiohttp/web_response.py' lineno=353>,)> size=5500000 (+5500000) count=100000 (+100000)>, <StatisticDiff traceback=<Traceback (<Frame filename='/Users/zhaofan/anaconda3/lib/python3.6/site-packages/aiohttp/web_response.py' lineno=352>,)> size=5300608 (+5300608) count=100001 (+100001)>,
我们拿第一行来说,我们可以非常清楚的指导web_response的56行代码导致内存增长的最多,当然如果是我们复杂的项目也可以通过类似的方法,这样就可以非常快捷的找到我们代码中哪些地方会造成内存溢出,便于排查问题,我们点进去看看这行代码:
我们找到最终行,这个时候我们大致就可以看出哪里的问题了,我们接着看 CIMultiDict
class CIMultiDict(MultiDict): def _title(self, key): return key.title()
我们可以看到这个它继承 MultiDict 其实这里我们已经应该知道问题就是处在这个MultiDict上了
而这个最终其实最终就是MultiDict这个包,问题出在了这个包上,这个项目是在这里维护的:https://github.com/aio-libs/multidict
查看这个包的时候看到了,果然有人和我遇到了同样的问题,问题就是出在这里了,已经有人提交了bug
https://github.com/aio-libs/multidict/issues/307
不过不得不说国外的程序员真的是热爱自己的职业,很快这个问题得到了aio-libs小组中人的回应,问题也在我整理这个博客的时候被修复了,在最新的版本:4.5.2中已经测试没有内存泄漏的问题
关于“python中如何解决内存泄漏问题”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。