最近工作中慢慢開始用python協程相關的東西,所以用到了一些相關模塊,如aiohttp, aiomysql, aioredis等,用的過程中也碰到的很多問題,這里整理了一次內存泄漏的問題
通常我們寫python程序的時候也很少關注內存這個問題(當然可能我的能力還有待提升),可能寫c和c++的朋友會更多的考慮這個問題,但是一旦我們的python程序出現了
內存泄漏的問題,也將是一件非常麻煩的事情了,而最近的一次代碼中也碰到了這個問題,不過好在最后內存溢出不是我代碼的問題,而是所用到的一個包出現了內存的問題,下面我通過一個簡單的代碼模擬出內存的問題,然后也會將解決的過程描述一下,希望能幫助到遇到同樣問題的朋友。
其實這次主要是在使用aiohttp寫一個接口的時候出現的問題,其實復現出問題非常容易,我們實現一個簡單的接受post請求接口的服務端,然后實現一個并發的客戶端來訪問這個接口,來查看內存的情況
注意: 這個問題是在一個包的特定版本出現的:multidict==4.5.1,
我在整理這個文章2個小時前作者已經修復了這個問題發布了4.5.2版本,已經修復了內存的問題,并且我也進行了測試驗證
服務端代碼:
from aiohttp import webasync def hello(request): return web.json_response(await request.json())app = web.Application()app.add_routes([web.post('/', hello)])web.run_app(app)
客戶端代碼:
import asyncioimport aiohttpasync 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
新聞熱點
疑難解答