import os
import xml.etree.ElementTree as et
for ev, el in et.iterparse(os.sys.stdin):
el.clear()
运行在ODP结构上面的RDF转储结果总是增加内存。 这是为什么? 我明白了ElementTree的还是建立一个解析树,尽管子节点clear()
版。 如果是这样的内存使用模式的原因,是有办法解决它?
import os
import xml.etree.ElementTree as et
for ev, el in et.iterparse(os.sys.stdin):
el.clear()
运行在ODP结构上面的RDF转储结果总是增加内存。 这是为什么? 我明白了ElementTree的还是建立一个解析树,尽管子节点clear()
版。 如果是这样的内存使用模式的原因,是有办法解决它?
你是clear
荷兰国际集团每一个元素,但对它们的引用留根文件内。 所以各个元素仍然不能被垃圾收集。 见这个讨论了ElementTree文档。
解决的办法是明确提到根,就像这样:
# get an iterable
context = iterparse(source, events=("start", "end"))
# turn it into an iterator
context = iter(context)
# get the root element
event, root = context.next()
for event, elem in context:
if event == "end" and elem.tag == "record":
... process record elements ...
root.clear()
要记住的内存使用,这可能不是会影响您的情况的另一件事是,一旦虚拟机分配从系统堆存储器,一般从不给内存回来。 大多数Java虚拟机的工作也是这样的。 所以,你不应该指望在解释的大小top
或ps
永远降低,即使堆内存的使用。
正如凯文·格拉在答复中提到,在“root.clear()”战略的ElementTree文档中能消除完全解析根的孩子。 如果这些孩子锚固巨大分支,它不是非常有帮助。
他谈到了理想的解决方案,但并没有发布任何代码,所以这里是一个例子:
element_stack = []
context = ET.iterparse(stream, events=('start', 'end'))
for event, elem in context:
if event == 'start':
element_stack.append(elem)
elif event == 'end':
element_stack.pop()
# see if elem is one of interest and do something with it here
if element_stack:
element_stack[-1].remove(elem)
del context
利益不会有子元素的元素; 他们会一直在尽快结束其标签被视为删除。 如果你需要的是元素的文字或属性,这可能是确定。
如果您想查询到该元素的后代,你需要让一个完整的分支来为它建造。 为此,保持一个标志,因为这些元素的深度计数器来实现。 只有调用一个.remove()时,深度为零:
element_stack = []
interesting_element_depth = 0
context = ET.iterparse(stream, events=('start', 'end'))
for event, elem in context:
if event == 'start':
element_stack.append(elem)
if elem.tag == 'foo':
interesting_element_depth += 1
elif event == 'end':
element_stack.pop()
if elem.tag == 'foo':
interesting_element_depth -= 1
# do something with elem and its descendants here
if element_stack and not interesting_element_depth:
element_stack[-1].remove(elem)
del context
我遇到了同样的问题。 文档没有使事情很清楚。 在我的情况的问题是:
1)调用清晰并释放内存的子节点。 文件说,它释放所有内存。 清除不释放那些明确被称为内存,因为该内存属于哪个分配它的母公司。 2)调用root.clear(),那要看是什么样的根。 如果根是父,然后它会工作。 否则,将不会释放内存。
此修复程序是保留对父的引用,当我们不再需要的节点,我们称之为parent.remove(child_node)。 这个工作,它保留了存储配置文件在几KB。