Skip to content

Instantly share code, notes, and snippets.

@naitoh
Last active May 12, 2024 09:47
Show Gist options
  • Save naitoh/abc5134fdf37bb3952e36f1fb77163b0 to your computer and use it in GitHub Desktop.
Save naitoh/abc5134fdf37bb3952e36f1fb77163b0 to your computer and use it in GitHub Desktop.
REXML dom/pull/libxml benchmark plot with Ruby 3.3 YJIT
# https://suer.hatenablog.com/entry/20110126/xml_parse の実験コードを参考にさせて頂きました。
require 'rubygems'
require 'gruff'
require 'benchmark'
require 'rexml/document'
require 'rexml/parsers/pullparser'
require 'xml/libxml'
# 最大子要素数
MAX = 10000
# 刻み
STEP = 100
g = Gruff::Line.new
RubyVM::YJIT.enable
def build_xml(n_elements, n_attributes)
xml = '<?xml version="1.0"?><root>'
n_elements.times do |i|
xml << '<child '
n_attributes.times {|j| xml << "id#{j}=\"#{i}\" " }
xml << '/>'
end
xml << '</root>'
end
# XMLの大きさを順次変更し、yield で渡して解析時間を計測する
# 返り値は計測した時間の配列
def bench
benchmarks = []
0.step(MAX, STEP) do |i|
xml = build_xml i, 2
benchmarks << Benchmark.measure do
yield xml
end
end
benchmarks.collect!{|b| b.total}
puts benchmarks.last
benchmarks
end
g.theme_37signals
puts "rexml(dom)"
# REXML で解析して plot
g.data("rexml(dom)",
bench do |xml|
REXML::Document.new(xml).elements.each("root/child") {|_|}
end
)
puts "rexml(pull)"
g.data("rexml(pull)",
bench do |xml|
parser = REXML::Parsers::PullParser.new(xml)
while parser.has_next?
parser.pull
end
end
)
puts "libxml-ruby(dom)"
# libxml-ruby で解析してplot
g.data("libxml-ruby(dom)",
bench do |xml|
XML::Document.string(xml).root.find('/root/child').each {|_|}
end
)
l = {}
0.step(MAX, MAX / 4) do |i|
l.merge!({i/STEP => i.to_s})
end
g.labels = l
g.x_axis_label = 'Number of lines'
g.y_axis_label = 'Seconds'
g.maximum_value = 0.2
g.minimum_value = 0
g.write('result.png')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment