Last active
December 1, 2015 21:05
-
-
Save backus/724b58b04c762f6c8ee6 to your computer and use it in GitHub Desktop.
HappyMapper flat vs. nested benchmark
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
XML = <<-EXML.freeze | |
<?xml version="1.0" encoding="utf-8" standalone="yes"?> | |
<foo> | |
<bar> | |
<baz> | |
<qux> | |
<quux> | |
<corge> | |
<grault> | |
<garply> | |
<waldo> | |
<fred> | |
<plugh> | |
<xyzzy> | |
<thud>Hello world!</thud> | |
</xyzzy> | |
</plugh> | |
</fred> | |
</waldo> | |
</garply> | |
</grault> | |
</corge> | |
</quux> | |
</qux> | |
</baz> | |
</bar> | |
</foo> | |
EXML | |
require 'nokogiri' | |
require 'happymapper' | |
class FlatMapper | |
include HappyMapper | |
tag 'foo' | |
has_one :thud, String, xpath: './bar/baz/qux/quux/corge/grault/garply/waldo/fred/plugh/xyzzy/thud' | |
end | |
class Xyzzy | |
include HappyMapper | |
tag 'xyzzy' | |
has_one :thud, String | |
end | |
class Plugh | |
include HappyMapper | |
tag 'plugh' | |
has_one :xyzzy, Xyzzy | |
end | |
class Fred | |
include HappyMapper | |
tag 'fred' | |
has_one :plugh, Plugh | |
end | |
class Waldo | |
include HappyMapper | |
tag 'waldo' | |
has_one :fred, Fred | |
end | |
class Garply | |
include HappyMapper | |
tag 'garply' | |
has_one :waldo, Waldo | |
end | |
class Grault | |
include HappyMapper | |
tag 'grault' | |
has_one :garply, Garply | |
end | |
class Corge | |
include HappyMapper | |
tag 'corge' | |
has_one :grault, Grault | |
end | |
class Quux | |
include HappyMapper | |
tag 'quux' | |
has_one :corge, Corge | |
end | |
class Qux | |
include HappyMapper | |
tag 'qux' | |
has_one :quux, Quux | |
end | |
class Baz | |
include HappyMapper | |
tag 'baz' | |
has_one :qux, Qux | |
end | |
class Bar | |
include HappyMapper | |
tag 'bar' | |
has_one :baz, Baz | |
end | |
class Foo | |
include HappyMapper | |
tag 'foo' | |
has_one :bar, Bar | |
end | |
class MapperBench | |
def self.flat | |
FlatMapper.parse(XML, single: true).thud | |
end | |
def self.nested | |
Foo.parse(XML, single: true).bar.baz.qux.quux.corge.grault.garply.waldo.fred.plugh.xyzzy.thud | |
end | |
end | |
require 'benchmark/ips' | |
Benchmark.ips do |x| | |
x.report('flat') { MapperBench.flat } | |
x.report('nested') { MapperBench.nested } | |
x.compare! | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Calculating ------------------------------------- | |
flat 339.000 i/100ms | |
nested 112.000 i/100ms | |
------------------------------------------------- | |
flat 3.690k (±16.8%) i/s - 17.967k | |
nested 1.117k (± 7.3%) i/s - 5.600k | |
Comparison: | |
flat: 3690.3 i/s | |
nested: 1116.7 i/s - 3.30x slower |
I mucked with the nokogiri source to log when it parses an XML document and as far as I can tell it does not re-parse. It does repeat a lot of work on each iteration though.
I think the most noteable difference is just that the FlatMapper
here does one xpath lookup and subsequent iteration over the nodes found where as this happens 12 times for the nested mappers
ah I see
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
indeed, is it grabbing xml and re-parsing?