Почему поиск узла с нужным текстом быстрее с ruby, чем с xpath? - PullRequest
0 голосов
/ 27 апреля 2018

Недавно мне пришлось проверить, содержат ли 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, но это не так. У кого-нибудь есть идея, почему?

1 Ответ

0 голосов
/ 27 апреля 2018

Обычно анализ и компиляция выражения XPath занимает намного больше времени, чем его выполнение, даже на довольно большом документе. Например, в Saxon при выполнении выражения count(//*[contains(., 'e')]) для исходного документа размером 1 МБ компиляция выражения пути занимает 200 мс, а выполнение - около 18 мс.

Если ваш XPath API позволяет вам скомпилировать выражение XPath один раз, а затем выполнить его многократно (или если оно кэширует скомпилированное выражение за кулисами), тогда определенно стоит воспользоваться этой возможностью.

Фактическое выполнение XPath, вероятно, будет, по крайней мере, так же быстро, как ваш рукописный навигационный код, возможно, скорее быстрее. Это подготовка, которая вызывает накладные расходы.

...