Skip to content

Instantly share code, notes, and snippets.

@backus
Last active December 1, 2015 21:05
Show Gist options
  • Save backus/724b58b04c762f6c8ee6 to your computer and use it in GitHub Desktop.
Save backus/724b58b04c762f6c8ee6 to your computer and use it in GitHub Desktop.
HappyMapper flat vs. nested benchmark
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
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
@OfTheDelmer
Copy link

indeed, is it grabbing xml and re-parsing?

@backus
Copy link
Author

backus commented Dec 1, 2015

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.

@backus
Copy link
Author

backus commented Dec 1, 2015

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

@OfTheDelmer
Copy link

ah I see

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment