【发布时间】:2019-10-29 23:23:09
【问题描述】:
如何调试 asyncio (with aiohttp) 应用程序以发现内存泄漏?
应用程序:100 个异步协程,从 Redis 读取消息,进行一些外部 API http 调用,并将结果保存到数据库中。
问题出在此处:消息数量越大 (10k-20k) 时,应用程序使用的 RAM 内存就会在每条消息后立即增加。
使用 objgraph 进行调试,例如:
print(objgraph.show_growth(limit=100))
在每条新消息后显示完全相同的结果:
weakref 6163 +4
dict 19192 +3
builtin_function_or_method 1911 +3
tuple 16880 +2
function 25375 +1
method 496 +1
Event 8 +1
Condition 8 +1
deque 14 +1
SplitResult 15 +1
Context 15 +1
Thread 7 +1
这一切都不是我亲手创建的,所以这都是第三方依赖。
还发现了有趣的项目:
其中一本词典(来自show_growth)是:
{'_context': <ssl.SSLContext object at 0x10a4ce228>,
'_server_side': False,
'_server_hostname':
'my.host.name',
'_state': 'SHUTDOWN',
'_incoming': <_ssl.MemoryBIO object at 0x10a620b30>,
'_outgoing': <_ssl.MemoryBIO object at 0x10a620b10>,
'_sslobj': <ssl.SSLObject object at 0x10a664ac8>,
'_need_ssldata': True,
'_handshake_cb': <bound method SSLProtocol._on_handshake_complete of <asyncio.sslproto.SSLProtocol object at 0x10a664630>>,
'_shutdown_cb': <bound method SSLProtocol._finalize of <asyncio.sslproto.SSLProtocol object at 0x10a664630>>
}
如您所见,这有点像调用或响应的结果。是否有可能,所有响应都在这里,所以它保存了每个响应并且 RAM 正在增加?
如何处理? 或者你能建议另一种方法来找到应用程序的薄弱环节吗?
【问题讨论】:
-
我发现用于跟踪内存泄漏的一个工具是pyrasite。您可以附加到正在运行的 Python 进程并在其中运行 REPL。
sys.getsizeof那个特定的字典可能是值得的,看看它是否真的随着时间的推移而增长。还要确保您使用的是最新版本的第三方库,因为我看到早期版本的 Python redis 库泄漏了内存,但它在以后的版本中得到了修复。 -
谢谢。实际上无法安装pyrasite,因为它与python3不兼容。使用 sys.getsizeof 获取大小不会返回任何有趣的结果,只有 100-200 字节
标签: python asynchronous python-asyncio aiohttp