【发布时间】:2020-08-21 14:47:07
【问题描述】:
我有一个长期运行的 CPython 3.8 进程。一段时间后,它使用了大量的 RAM。 我试过了
- 正在运行 gc.collect()
- 使用 pymler 发现所有已知的 Python 对象
import gc
import psutil
from pympler import muppy, summarize
gc.collect()
total_ram = psutil.Process().memory_info().rss
all_objects = muppy.get_objects(include_frames=True)
s = summary.summarize(all_objects)
python_objects_size = sum(row[2] for row in s)
输出:102 MiB Python 对象,824 MiB RSS 内存!
[编辑] 3. 使用 tracemalloc;它还返回价值约 100MiB 的 python 对象
[编辑 2]export PYTHONMALLOC=malloc 没有解决问题。
有没有办法查询CPython内存管理器来弄清楚
- 它拥有多少 RAM,这样我就可以从 RSS 中减去它并确定是否有任何 C 库未使用 PyMem_Malloc 并且正在泄漏
- 为什么它持有内存(例如,发现它持有一个 64kb 的页面,因为一个 20 字节的 PyObject 仍在被引用)
- 识别调用 PyMem_Malloc 之后从未释放内存的 C 模块
- 跟踪操作系统级别的 malloc() 和 free() 并将它们与 pymalloc 执行的进行交叉比较,以确定是否有 C 库分配内存而不是 PyMem_Malloc
相关
- Calculating memory fragmentation in Python(2012 年;同样的问题,但从未回答)
- Does CPython's garbage collection do compaction?(答案:否)
【问题讨论】:
-
tracemalloc 发出的信息总计约 100MB - 与 pymler 报告的大致相同。 memory_profiler 给了我被大大低估的结果;例如如果我分配一个包含 100k 随机浮点数的列表,memory_profiles 表示该行消耗了 0.3 MiB,同时它报告 RSS 上升了 3.8 MiB。
-
不是一个真正的答案......几个月前我们在我的工作中遇到了类似的问题。在花了一些时间使用垃圾收集分析器之后,我们最终使用古老的分而治之的方法解决了这个问题:删除一些代码,看看问题是否仍然存在,而不是删除更多,等等等等(还有一些之后还有更多等等 - 但它让我们最终能够解决问题)。