我的 python 调试技能有点生疏(我的意思是我最后一次在 Orbited(websockets 的前身)上使用 objgraph 是在 2009 年https://pypi.python.org/pypi/orbited),但据我所知,检查之前和之后的引用数量:
使用之前和之后计算调度程序中的对象objgraph.show_most_common_types()
| What | Before | After | Diff |
|-------------+------------------+--------|---------+
| function | 33318 | 33399 | 81 |
| dict | 17988 | 18277 | 289 |
| tuple | 16439 | 28062 | 11623 |
| list | 10926 | 11257 | 331 |
| OrderedDict | N/A | 7168 | 7168|
在任何情况下它都不是大量的 RAM,但是深入挖掘我发现 t scheduler._transition_counter 是 11453 并且 scheduler.transition_log 充满了:
('x-25ca747a80f8057c081bf1bca6ddd481', 'released', 'waiting',
OrderedDict([('x-25ca747a80f8057c081bf1bca6ddd481', 'processing')]), 4121),
('x-25ca747a80f8057c081bf1bca6ddd481', 'waiting', 'processing', {}, 4122),
('x-25cb592650bd793a4123f2df39a54e29', 'memory', 'released', OrderedDict(), 4123),
('x-25cb592650bd793a4123f2df39a54e29', 'released', 'forgotten', {}, 4124),
('x-25ca747a80f8057c081bf1bca6ddd481', 'processing', 'memory', OrderedDict(), 4125),
('x-b6621de1a823857d2f206fbe8afbeb46', 'released', 'waiting', OrderedDict([('x-b6621de1a823857d2f206fbe8afbeb46', 'processing')]), 4126)
我
的第一个错误当然这让我意识到我的第一个错误是没有配置转换日志长度。
将配置设置transition-log-length
为 10 后:
| What | Before | After | Diff |
| ---------------+----------+--------+---------|
| function | 33323 | 33336 | 13 |
| dict | 17987 | 18120 | 133 |
| tuple | 16530 | 16342 | -188 |
| list | 10928 | 11136 | 208 |
| _lru_list_elem | N/A | 5609 | 5609 |
一个快速的谷歌发现它_lru_list_elem
是由@functools.lru_cache
它在key_split (in distributed/utils.py
)中调用的
这是 LRU 缓存,最多可容纳 100 000 个项目。
第二次尝试
根据代码,它显示为 Dask 应该攀升到大约 10k_lru_list_elem
在再次运行我的脚本并观察内存之后,它会快速攀升,直到我接近 100k _lru_list_elem,之后它几乎完全停止了攀升。
情况似乎是这样,因为它在 100k 之后几乎是平线

所以没有泄漏,但是在 Dask 源代码和 Python 内存分析器上弄脏手很有趣