我有一个网络进程,该进程通过TCP进行通信,以收集数据,将其反序列化并最终将其部分存储在LevelDB键/值存储中(通过Plyvel)。
随着时间的流逝,它将消耗所有可用内存,直至整个系统锁定(Ubuntu 18.04)。我正在尝试诊断原因,但是用尽了如何进一步调查的想法。
我想到的主要怀疑对象是我们用来反序列化对象的数据流。在那里完成的一般操作是:从asyncio.StreamReader接收数据并调用deserialize_from_bytes
(请参见下一个)
@classmethod
def deserialize_from_bytes(cls, data_stream: Union[bytes, bytearray]):
""" Deserialize object from a byte array. """
br = BinaryReader(stream=data_stream)
inv_payload = cls()
try:
inv_payload.deserialize(br)
except ValueError:
return None
finally:
br.cleanup()
return inv_payload
BinaryReader
的初始化方式如下
def __init__(self, stream: Union[io.BytesIO, bytes, bytearray]) -> None:
super(BinaryReader, self).__init__()
if isinstance(stream, (bytearray, bytes)):
self._stream = io.BytesIO(stream)
else:
self._stream = stream
和cleanup()
是self._stream.close()
我尝试过的事情
我首先尝试了tracemalloc
的{{3}}代码段。在/proc/$mypid/status
的内存使用量为2GB(由VmSize
表示)的时间点上,tracemalloc
中消耗最大的项仅报告了38MB,其次是第二个和第三个是3MB, 360Kb。
这已经引起了一个问题;其他〜1.958 GB在哪里?
我尝试display top 10的上述输出没有帮助。我使用pdb
进入了流程,并使用
import objgraph
objgraph.show_most_common_types(limit=20)
获得
function 16451
tuple 11456
dict 10371
weakref 3058
list 2893
cell 2446
Traceback 2277
Statistic 2277
_Binding 2109
getset_descriptor 1814
type 1680
builtin_function_or_method 1469
wrapper_descriptor 1311
method_descriptor 1284
frozenset 992
property 983
module 810
ModuleSpec 808
SourceFileLoader 738
Attrs 593
在该列表中我没有看到任何特定于我的程序的对象(这可能表示未释放引用)。在其他objgraph
实例中,我发现上述计数似乎与众不同。我检查了两个function
对象,并始终发现与此类似的东西(与异步有关),这并不表示有任何暗示。内存在那里泄漏
(Pdb) objgraph.at(0x10f309b70)
<function _run_coroutine.<locals>.step_next.<locals>.continue_ at 0x10f309b70>
如果我缺少一些东西,请在这里纠正我。再次,没有进一步的步骤
gc.set_debug(gc.DEBUG_LEAK)
运行该程序,但这产生了太多的输出,我什么都做不了。有什么提示可以从这里开始尝试吗?