-
-
Notifications
You must be signed in to change notification settings - Fork 905
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
explore: optimize Node#at_css
and #at_xpath
#2213
Comments
Holy cow, I just discovered that libxml2 will automatically try to optimize any expression of the form #! /usr/bin/env ruby
require "bundler/inline"
gemfile do
source "https://rubygems.org"
gem "nokogiri", path: "."
gem "benchmark-ips"
end
xml = "<root>" +
(1..2000).map { |i| "<item>#{i}</item>" }.join +
"</root>"
doc = Nokogiri::XML(xml)
Benchmark.ips do |x|
x.report("optimized xpath") do
result = doc.xpath("(//item)[1]")
raise "unexpected result" unless result.size == 1
end
x.report("unoptimized xpath") do
result = doc.xpath("//item[1]")
raise "unexpected result" unless result.size == 1
end
x.compare!
end reports
Seems like, other than having to deal with the crappy positional arguments for all the methods in |
Hmm, actually this may not be as big of a win as I thought for some reason ... xml = "<root>" +
(1..2000).map { |i| "<item>#{i}</item>" }.join +
"</root>"
doc = Nokogiri::XML(xml)
Benchmark.ips do |x|
x.report("optimized xpath") do
doc.xpath("(//item)[1]")
end
x.report("unoptimized xpath") do
doc.at_xpath("//item")
end
x.compare!
end reports
Weird. |
OK, this has something to do with how expensive the node's context position is to calculate. If I replace
Shrug, I'm not sure it's worth making this part of |
Currently,
#at_css
and#at_xpath
execute the entire XPath query with multiple results, creates the NodeSet and wraps each result as a Ruby object before discarding all but the first result.It should be possible to optimize this, both at the XPath layer and while marshalling results.
At the XPath layer, let's play with variations of
(original-query)[1]
At the marshalling layer, let's discard the NodeSet and just return the single Ruby object.
The text was updated successfully, but these errors were encountered: