提问人:Diomidis Spinellis 提问时间:11/27/2022 最后编辑:Diomidis Spinellis 更新时间:11/27/2022 访问量:79
如何修复对 Python 的 XML 树解析器的调用中的长时间停顿?
How to fix long pauses within calls to Python's XML tree parser?
问:
在 Python 程序中,我反复调用以解析每个 4k 到 6MB 的独立 XML 文档。对分析器的大多数调用在 1 毫秒内完成。然而,经过 17 个小时的处理和解析大约 1100 万个文档后,该过程变得越来越慢,解析单个小(例如 14 kB)XML 文档需要一分钟多甚至五分钟。此暂停每两万块重复一次。在暂停期间,Python(版本 3.7.3)不会调用任何系统或库函数,而是完全占用运行它的 CPU 内核。对调用堆栈的检查显示以下函数:xml.etree.ElementTree.fromstring
#0 0x000000000050fcc0 in ?? ()
#1 0x00000000005897df in ?? ()
#2 0x0000000000518776 in ?? ()
#3 0x0000000000519fc5 in _PyObject_GC_New ()
#4 0x00000000005bcf6a in PyList_New ()
#7 0x00007ff88be4491e in ?? () from /lib/x86_64-linux-gnu/libexpat.so.1
#8 0x00007ff88be454bc in ?? () from /lib/x86_64-linux-gnu/libexpat.so.1
#9 0x00007ff88be42f8b in ?? () from /lib/x86_64-linux-gnu/libexpat.so.1
#10 0x00007ff88be43e7b in ?? () from /lib/x86_64-linux-gnu/libexpat.so.1
#11 0x00007ff88be47a38 in XML_ParseBuffer ()
from /lib/x86_64-linux-gnu/libexpat.so.1
#14 0x00000000005ccba1 in _PyMethodDef_RawFastCallKeywords ()
#16 0x000000000054653a in _PyEval_EvalFrameDefault ()
#17 0x000000000053f732 in _PyEval_EvalCodeWithName ()
#18 0x00000000005cd982 in _PyFunction_FastCallKeywords ()
#20 0x000000000054653a in _PyEval_EvalFrameDefault ()
#21 0x000000000053f732 in _PyEval_EvalCodeWithName ()
[…]
在暂停开始发生时,Python 进程占用 12.1 GB 的虚拟内存,其中 8.7 GB 驻留在具有另外 60 GB 可用 RAM 的计算机上。我发现内存消耗过多,因为我没有在内存中保留任何数据:我将每个文档中的选定数据写入SQLite数据库。
我怀疑这个问题与与 Python 或 XML 解析库相关的病态低效内存管理有关。关于如何解决它的任何想法?我是否可以以某种方式在调用之间重置 XML 解析器状态,或者在堆的结构变得无法忍受的复杂之前先发制人地执行垃圾回收?等待 17 小时来尝试每个可能的修复程序,我更愿意听到知道解决方案的人的意见,而不是自己尝试各种可能的修复程序。
答: 暂无答案
评论