我正在解析由大约135k或多或少类似记录组成的大型(12 GB)XML文件(这是一个nmap转储)。我注意到解析速度不一致,解析类似记录的时间变化很大。
以下缩小的代码输出解析每1%记录所需的时间:
from xml.etree.ElementTree import iterparse
import time
nrhosts = 0
previous = time.time()
context = iterparse("test.xml", events=("start", "end"))
context = iter(context)
event, root = context.next()
for event, elem in context:
if event == 'end' and elem.tag == "host":
root.clear() # clean up memory
nrhosts += 1
if nrhosts % 1349 == 0: # hardcoded to estimate the % as there are ~135k of records
now = time.time()
print nrhosts // 1349, now - previous
previous = now
这给出了:
1 2.43700003624
2 3.13999986649
3 2.87700009346
4 2.59200000763
5 65.8800001144
6 47.6069998741
7 43.6809999943
8 29.7590000629
9 11.8629999161
10 4.52200007439
11 40.0160000324
12 42.2109999657
13 45.9930000305
14 29.1139998436
15 6.18600010872
16 41.7149999142
17 40.3410000801
18 40.0460000038
19 30.2319998741
20 1.45700001717
21 5.35100007057
22 15.4260001183
23 32.7389998436
24 42.7220001221
25 10.4960000515
26 1.28299999237
27 7.33299994469
28 22.7130000591
29 27.3199999332
30 34.4129998684
31 1.71200013161
32 1.63499999046
33 7.06900000572
34 24.1480000019
35 25.7660000324
36 20.8759999275
37 1.29399991035
38 1.34899997711
39 5.71700000763
40 35.9170000553
41 33.8300001621
42 8.69299983978
43 1.35500001907
44 1.3180000782
45 8.44099998474
46 26.1540000439
47 28.768999815
48 5.91400003433
49 1.63499999046
50 1.30800008774
51 5.93499994278
这个输出看起来令人惊讶地“波浪”:
surprisingly wavy http://i.minus.com/ibiIth8t2AFf4t.png:
我想强调一下:
nmap -O
的输出,因此每条记录的信息量(在我的情况下为<host>
)或多或少相同。我想说的是,XML输出中没有任何内容可以使某些部分“更长”来解析。我的代码中的任何内容都会暗示这种行为吗? (我使用SAX来处理XML文件的大小,也许有一些固有的东西可以修改解析速度?)。
我的目标是最终了解“这是生命”,只是接受事实或修改我的代码。
谢谢。
答案 0 :(得分:0)
我知道这可能是一个愚蠢的问题,但您是否尝试过使用XML库的C实现?尝试导入
from xml.etree.cElementTree import iterparse
这应该会给你一个很大的速度提升。如果仍然不够,我会尝试使用lxml XML解析器http://lxml.de/
此外,我不确定是否可以将XML文件拆分为块,以便您可以利用多处理来有效利用多个CPU核心,然后将结果合并回单个数据结构。
答案 1 :(得分:0)
此图几乎是缓存系统的指纹! :-) 您以块的形式读取文件(如ElementTree实现中所定义),但计算机会在假设您很快需要下一个块的情况下读取更多内容。这意味着您处理的下一个块将需要更少的时间,因为它已经在内存中等等。但是,在某个时刻,内存中的缓冲区几乎是空的。正是在这个时刻,你需要“等待”一段时间才能读取下一个块,从而增加你的测量结果。