最近我不得不检查html节点是否包含所需的文本。我很惊讶当我重构代码以使用xpath选择器时,它变得慢了10倍。有基准
的原始代码的简化版本# has_keyword_benchmark.rb
require 'benchmark'
require 'nokogiri'
Doc = Nokogiri("
<div>
<div>
A
</div>
<p>
<b>A</b>
</p>
<span>
B
</span>
</div>")
def has_keywords_with_xpath
Doc.xpath('./*[contains(., "A")]').size > 0
end
def has_keywords_with_ruby
Doc.text.include? 'A'
end
iterations = 10_000
Benchmark.bm(27) do |bm|
bm.report('checking if has keywords with xpath') do
iterations.times do
has_keywords_with_xpath
end
end
bm.report('checking if has keywords with ruby') do
iterations.times do
has_keywords_with_ruby
end
end
end
当我运行ruby has_keyword_benchmark.rb
时,我得到了
user system total real
checking if has keywords with xpath 0.400000 0.020000 0.420000 ( 0.428484)
checking if has keywords with ruby 0.020000 0.000000 0.020000 ( 0.023773)
使用xpath直观地检查节点是否有某些文本应该更快,但事实并非如此。有人知道为什么吗?
答案 0 :(得分:2)
通常,解析和编译XPath表达式比实际执行它需要更长的时间,即使在相当大的文档上也是如此。例如,对于Saxon,对1Mb源文档运行表达式count(//*[contains(., 'e')])
,编译路径表达式需要200ms,而执行它需要大约18ms。
如果您的XPath API允许您编译一次XPath表达式然后重复执行它(或者如果它在后台缓存编译后的表达式),那么绝对值得利用该功能。
实际的XPath执行可能至少与手写的导航代码一样快,可能更快。这是导致开销的准备。