#!/usr/bin/env ruby -wW1 $: << '.' $: << '..' $: << '../lib' $: << '../ext' if __FILE__ == $0 while (i = ARGV.index('-I')) x,path = ARGV.slice!(i, 2) $: << path end end require 'optparse' require 'ox' require 'sample' require 'files' begin require 'nokogiri' rescue Exception => e end begin require 'libxml' rescue Exception => e end $verbose = 0 $ox_only = false $all_cbs = false $filename = nil # nil indicates new file names perf.xml will be created and used $filesize = 1000 # KBytes $iter = 100 opts = OptionParser.new opts.on("-v", "increase verbosity") { $verbose += 1 } opts.on("-x", "ox only") { $ox_only = true } opts.on("-a", "all callbacks") { $all_cbs = true } opts.on("-f", "--file [String]", String, "filename") { |f| $filename = f } opts.on("-i", "--iterations [Int]", Integer, "iterations") { |i| $iter = i } opts.on("-s", "--size [Int]", Integer, "file size in KBytes") { |s| $filesize = s } opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) } rest = opts.parse(ARGV) $xml_str = nil $ox_time = 0 $no_time = 0 $lx_time = 0 # size is in Kbytes def create_file(filename, size) head = %{ } tail = %{
} row = %{ 1234 A string. This is a longer string that stretches over a larger number of characters. -12.345 2011-09-18 23:07:26 +0900 } cnt = (size * 1000 - head.size - tail.size) / row.size File.open(filename, "w") do |f| f.write(head) cnt.times do |i| f.write(row % [i,i]) end f.write(tail) end end class OxSax < ::Ox::Sax def error(message, line, column); puts message; end end class OxAllSax < OxSax def start_element(name); end def attr(name, value); end def end_element(name); end def text(value); end def instruct(target); end def doctype(value); end def comment(value); end def cdata(value); end end unless defined?(::Nokogiri).nil? class NoSax < Nokogiri::XML::SAX::Document def error(message); puts message; end def warning(message); puts message; end end class NoAllSax < NoSax def start_element(name, attrs = []); end def characters(text); end def cdata_block(string); end def comment(string); end def end_document(); end def end_element(name); end def start_document(); end def xmldecl(version, encoding, standalone); end end end unless defined?(::LibXML).nil? class LxSax include LibXML::XML::SaxParser::Callbacks end class LxAllSax < LxSax def on_start_element(element, attributes); end def on_cdata_block(cdata); end def on_characters(chars); end def on_comment(msg); end def on_end_document(); end def on_end_element(element); end def on_end_element_ns(name, prefix, uri); end def on_error(msg); end def on_external_subset(name, external_id, system_id); end def on_has_external_subset(); end def on_has_internal_subset(); end def on_internal_subset(name, external_id, system_id); end def on_is_standalone(); end def on_processing_instruction(target, data); end def on_reference(name); end def on_start_document(); end def on_start_element_ns(name, attributes, prefix, uri, namespaces); end end end def perf_stringio() start = Time.now handler = $all_cbs ? OxAllSax.new() : OxSax.new() $iter.times do input = StringIO.new($xml_str) Ox.sax_parse(handler, input) input.close end $ox_time = Time.now - start puts "StringIO SAX parsing #{$iter} times with Ox took #{$ox_time} seconds." return if $ox_only unless defined?(::Nokogiri).nil? handler = Nokogiri::XML::SAX::Parser.new($all_cbs ? NoAllSax.new() : NoSax.new()) start = Time.now $iter.times do input = StringIO.new($xml_str) handler.parse(input) input.close end $no_time = Time.now - start puts "StringIO SAX parsing #{$iter} times with Nokogiri took #{$no_time} seconds." end unless defined?(::LibXML).nil? start = Time.now $iter.times do input = StringIO.new($xml_str) parser = LibXML::XML::SaxParser.io(input) parser.callbacks = $all_cbs ? LxAllSax.new() : LxSax.new() parser.parse input.close end $lx_time = Time.now - start puts "StringIO SAX parsing #{$iter} times with LibXML took #{$lx_time} seconds." end puts "\n" puts ">>> Ox is %0.1f faster than Nokogiri SAX parsing using StringIO." % [$no_time/$ox_time] unless defined?(::Nokogiri).nil? puts ">>> Ox is %0.1f faster than LibXML SAX parsing using StringIO." % [$lx_time/$ox_time] unless defined?(::LibXML).nil? puts "\n" end def perf_fileio() puts "\n" puts "A #{$filesize} KByte XML file was parsed #{$iter} times for this test." puts "\n" start = Time.now handler = $all_cbs ? OxAllSax.new() : OxSax.new() $iter.times do input = IO.open(IO.sysopen($filename)) Ox.sax_parse(handler, input) input.close end $ox_time = Time.now - start puts "File IO SAX parsing #{$iter} times with Ox took #{$ox_time} seconds." return if $ox_only unless defined?(::Nokogiri).nil? handler = Nokogiri::XML::SAX::Parser.new($all_cbs ? NoAllSax.new() : NoSax.new()) start = Time.now $iter.times do input = IO.open(IO.sysopen($filename)) handler.parse(input) input.close end $no_time = Time.now - start puts "File IO SAX parsing #{$iter} times with Nokogiri took #{$no_time} seconds." end unless defined?(::LibXML).nil? start = Time.now $iter.times do input = IO.open(IO.sysopen($filename)) parser = LibXML::XML::SaxParser.io(input) parser.callbacks = $all_cbs ? LxAllSax.new() : LxSax.new() parser.parse input.close end $lx_time = Time.now - start puts "File IO SAX parsing #{$iter} times with LibXML took #{$lx_time} seconds." end puts "\n" puts ">>> Ox is %0.1f faster than Nokogiri SAX parsing using file IO." % [$no_time/$ox_time] unless defined?(::Nokogiri).nil? puts ">>> Ox is %0.1f faster than LibXML SAX parsing using file IO." % [$lx_time/$ox_time] unless defined?(::LibXML).nil? puts "\n" end if $filename.nil? create_file('perf.xml', $filesize) $filename = 'perf.xml' end $xml_str = File.read($filename) # perf_stringio() perf_fileio()