1

我正在使用 Python 2.7 的difflib.HtmlDiff.make_table()函数为内部测试用例运行程序生成预期文件和实际文件之间的差异。它们最终形成 HTML 测试报告。

到目前为止,这工作得很好——直到我添加了一个带有更大文件(~400 KiB)的测试用例,有很多差异,通常不包含换行符。几乎我所有的测试用例都在不到 2 秒的时间内执行,一些更复杂的测试用例甚至高达 4 秒。这个新的在通过时同样快,但需要 13 分钟(!)才能失败。所有这些时间都花在生成报告上。我希望你能看到这是一个问题。

试图证明这一点(我知道可能不是最好的方法):

s = """import os, difflib
a = [os.urandom(length)]
b = [os.urandom(length)]
difflib.HtmlDiff().make_table(a, b)"""

import timeit
print 'length    100:', timeit.timeit(s, setup='length = 100', number=1)
print 'length   1000:', timeit.timeit(s, setup='length = 1000', number=1)
print 'length  10000:', timeit.timeit(s, setup='length = 10000', number=1)
print 'length 100000:', timeit.timeit(s, setup='length = 100000', number=1)
print 'length 400000:', timeit.timeit(s, setup='length = 400000', number=1)

结果:

length    100: 0.022672659081
length   1000: 0.0125987213238
length  10000: 0.479898318086
length 100000: 54.9947423284
length 400000: 1451.59828412

difflib.ndiff()make_table()据我了解,内部使用)似乎没有这个问题:

s = """import os, difflib
a = [os.urandom(length)]
b = [os.urandom(length)]
difflib.ndiff(a, b)"""

import timeit
print 'length    100:', timeit.timeit(s, setup='length = 100', number=100)
print 'length   1000:', timeit.timeit(s, setup='length = 1000', number=100)
print 'length  10000:', timeit.timeit(s, setup='length = 10000', number=100)
print 'length 100000:', timeit.timeit(s, setup='length = 100000', number=100)
print 'length 400000:', timeit.timeit(s, setup='length = 400000', number=100)

给我这个:

length    100: 0.0233492320197
length   1000: 0.00770079984919
length  10000: 0.0672924110913
length 100000: 0.480133018906
length 400000: 1.866792587

这看起来很合理,即它是成比例的。四倍的大小需要四倍的时间。


不知道从这里去哪里。我猜当存在差异时,HTML 生成器会进行大量回溯(尽管您会认为 ndiff() 已经处理了该问题)。我可以告诉它提前中止,放弃并将整个部分标记为“不同”吗?

我知道有很多不同的算法可以生成差异。在这种情况下,我不需要它进行非常深入的分析并尝试在任何地方重新同步。我只需要它大致告诉我文件上的哪个位置不同,然后在合理的时间范围内终止。

或者,是否有其他生成 HTML 的 Python 差异库没有这种最坏情况的问题?

4

1 回答 1

0

与此相关的 CPython 问题:

于 2013-02-23T19:06:58.997 回答