我运行一个服务器,作为团队内客户的数据处理节点。最近,我们一直在重构服务器中的遗留代码,以利用 numpy 进行某些过滤/转换作业。
由于我们必须将此数据提供给远程客户端,我们将numpy数据转换为各种形式,使用 numpy.tolist()作为中间步骤。
每个查询都是无状态的,没有全局变量,因此在查询之间不会维护任何引用。
在一个特定的步骤中,我得到明显的内存泄漏,我一直试图通过 memory_profiler 来追踪。该步骤涉及将大的(> 4m条目)ndarray的浮点数转换为python列表。我第一次发出查询时,tolist()调用分配120m内存,然后在释放numpy数组时释放31m。第二个(以及随后的时间)我发出相同的查询,分配/解除分配是31米。我发出的每个不同查询都具有相同的模式,但具有不同的绝对值。
我已经拆开了我的代码,并强制执行一些del命令以用于说明目的。下面的输出来自 memory_profiler.profile
第一期查询:
Line # Mem usage Increment Line Contents
================================================
865 296.6 MiB 0.0 MiB p = ikeyData[1]['value']
866 417.2 MiB 120.6 MiB newArr = p.tolist()
867 417.2 MiB 0.0 MiB del p
868 385.6 MiB -31.6 MiB del ikeyData[1]['value']
869 385.6 MiB 0.0 MiB ikeyData[1]['value'] = newArr
同一查询的第二个(及后续)实例:
Line # Mem usage Increment Line Contents
================================================
865 494.7 MiB 0.0 MiB p = ikeyData[1]['value']
866 526.3 MiB 31.6 MiB newArr = p.tolist()
867 526.3 MiB 0.0 MiB del p
868 494.7 MiB -31.6 MiB del ikeyData[1]['value']
869 494.7 MiB 0.0 MiB ikeyData[1]['value'] = newArr
可以想象,在长期运行的高可变查询过程中,这些分配会迫使我们定期退回服务器。
有没有人想过这里会发生什么?
答案 0 :(得分:1)
在你的情况下,Python可能已经释放了内存。
这并不意味着内存分配器必然会返回内存
到操作系统。 memory_profiler
使用系统调用来查找当前使用的内存量。所以你的代码可能没什么问题。