5

我正在解析一个由大约 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

这个输出看起来令人惊讶地“波浪状”:

令人惊讶的波浪 http://i.minus.com/ibiIth8t2AFf4t.png

我想强调一点:

  • 运行代码的机器是安静的(没有什么特别的事情会干扰解析)。我在运行 Win7 的笔记本电脑和运行 Debian 的 ESX 上的 VM 上得到了类似的结果(在解析速度变化很大的意义上类似)
  • 记录或多或少相同:XML 文件是一个输出,nmap -O因此每条记录(在我的情况下为 a)的信息量<host>或多或少相同。我想说的是,XML 输出中没有任何内容可以使某些部分“更长”地解析。

我的代码中的任何内容都会暗示这种行为吗?(我使用 SAX 来处理 XML 文件的大小,也许有一些固有的东西会改变解析速度?)。

我的最终目标是了解“这是否就是生活”并接受事实或修改我的代码。

谢谢你。

4

2 回答 2

0

这张图几乎是缓存系统的指纹!:-) 您以块的形式读取文件(如 ElementTree 实现中所定义),但计算机会在您很快需要下一个块的假设下读取更多内容。这意味着您处理的下一个块将需要更少的时间,因为它已经在内存中等等。但是,在某个时刻,内存中的缓冲区几乎是空的。正是在这一刻,您需要“等待”一段时间才能读取下一个块,从而增加您的测量值。

于 2014-02-27T10:46:41.913 回答
0

我知道这可能是一个愚蠢的问题,但是您是否尝试过使用 XML 库的 C 实现?尝试导入

from xml.etree.cElementTree import iterparse

这应该会给你一个很大的速度提升。如果还不够,我会尝试使用 lxml XML 解析器http://lxml.de/

此外,我不确定是否可以将 XML 文件拆分为多个块,以便您可以利用多处理来有效地利用多个 CPU 内核,然后将结果合并回单个数据结构。

于 2013-11-04T21:41:45.930 回答