Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Benchmark of using different methods to convert complex Mash to Hash

Using the following Gem versions:

  • benchmark-ips (2.1.0)
  • chef (11.16.4), which includes:
    • erubis (2.7.0)
    • json (1.8.1)

Ruby 1.9.3:

Calculating -------------------------------------
         monkeypatch    75.000  i/100ms
      mash2json2yaml    73.000  i/100ms
-------------------------------------------------
         monkeypatch    745.984  (± 9.9%) i/s -      3.750k
      mash2json2yaml    761.028  (± 7.9%) i/s -      3.796k

Comparison:
      mash2json2yaml:      761.0 i/s
         monkeypatch:      746.0 i/s - 1.02x slower

Ruby 2.1.5:

Calculating -------------------------------------
         monkeypatch    88.000  i/100ms
      mash2json2yaml    86.000  i/100ms
-------------------------------------------------
         monkeypatch    884.203  (± 4.0%) i/s -      4.488k
      mash2json2yaml    865.697  (± 3.8%) i/s -      4.386k

Comparison:
         monkeypatch:      884.2 i/s
      mash2json2yaml:      865.7 i/s - 1.02x slower
require 'benchmark/ips'
require 'chef'
require 'erubis'
HASHDATA = {
'conf' => [
{
'exclude' => [
{
'domain' => 'evil_domain'
}
],
'include' => {
'attribute' => {
'bytesReceived' => { 'metric_type' => 'counter', 'alias' => 'tomcat.bytes_rcvd' },
'maxThreads' => { 'metric_type' => 'gauge', 'alias' => 'tomcat.threads.max' }
},
'bean' => 'tomcat_bean',
'domain' => 'domain0',
'type' => 'ThreadPool'
},
'include' => {
'attributes' => [
'BloomFilterDiskSpaceUsed',
'Capacity'
],
'bean_name' => 'com.datadoghq.test:type=BeanType,tag1=my_bean_name',
'domain' => 'org.apache.cassandra.db',
'foo' => 'bar'
}
}
],
'extra_key' => 'extra_val',
'host' => 'localhost',
'port' => 9999
}
# Simulate Attribute loading by creating the Mash directly
MASH1 = Chef::Node::ImmutableMash.new(HASHDATA)
MASH2 = Chef::Node::ImmutableMash.new(HASHDATA)
@mash_array = Chef::Node::ImmutableArray.new [MASH1, MASH2]
# Monkeypatching of Chef classes to provide `deep` class conversion
class Chef
class Node
class ImmutableMash
def deep_to_hash
h = {}
self.each do |k,v|
if v.respond_to?('deep_to_hash')
h[k] = v.deep_to_hash
elsif v.respond_to?('deep_to_a')
h[k] = v.deep_to_a
else
h[k] = v
end
end
return h
end
end
class ImmutableArray
def deep_to_a
a = []
self.each do |v|
if v.respond_to?('deep_to_hash')
a << v.deep_to_hash
elsif v.respond_to?('deep_to_a')
a << v.deep_to_a
else
a << v
end
end
return a
end
end
end
end
# Common render method for benchmarks
def render(template)
eruby = Erubis::Eruby.new(template)
output = eruby.evaluate(Erubis::Context)
end
def monkeypatch
render("<%= YAML.dump({ 'instances' => #{@mash_array.deep_to_a} }) %>")
end
def mash2json2yaml
render("<%= JSON.parse(({ 'instances' => #{@mash_array}.to_a }).to_json).to_yaml %>")
end
Benchmark.ips do |x|
x.report('monkeypatch') { monkeypatch }
x.report('mash2json2yaml') { mash2json2yaml }
x.compare!
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment