【问题标题】:Slowly increasing memory usage of Dask ShedulerDask Scheduler的内存使用缓慢增加
【发布时间】:2018-03-16 00:46:33
【问题描述】:

我正在测试:

client = Client('127.0.0.1:8786')

def x(i):
    return {}

while True:
    start = time.time()
    a = client.submit(randint(0,1000000))
    res = a.result()
    del a
    end = time.time()
    print("Ran on %s with res %s" % (end-start, res))

client.shutdown()
del client

我使用它(带有更多代码)来估计我的查询性能。但是对于这个例子,我已经删除了所有我能想到的东西。

上面的代码大约每秒泄漏 0.1 MB,我估计每 1000 次调用大约 0.3 MB。

我的代码做错了吗?

【问题讨论】:

    标签: dask dask-distributed


    【解决方案1】:

    我的 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 又调用了distributed/utils.py(在distributed/utils.py 中)

    这是 LRU 缓存,最多 100 000 个项目。

    第二次尝试
    根据代码,它显示为 Dask 应该上升到大约 10k _lru_list_elem

    在再次运行我的脚本并观察内存后,它会快速攀升,直到我接近 100k _lru_list_elem,之后它几乎完全停止了攀升。

    似乎是这样,因为它在 100k 之后几乎是平线

    所以没有泄漏,但接触 Dask 源代码和 Python 内存分析器很有趣

    【讨论】:

      【解决方案2】:

      出于诊断、日志记录和性能方面的原因,Dask 调度程序会记录其与固定大小的双端队列中的工作人员和客户端的许多交互。这些记录确实会累积,但只是在有限的范围内。

      我们还努力确保不会保留任何过大的东西。

      看到内存使用量不断攀升,直到一个不错的整数,就像你所看到的那样,然后保持稳定似乎与此一致。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-04-09
        • 1970-01-01
        • 2021-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-17
        • 2018-01-03
        相关资源
        最近更新 更多