Skip to content

Instantly share code, notes, and snippets.

@kbrock
Forked from aishfenton/serializer_benchmarks.rb
Last active August 29, 2017 13:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kbrock/978baec148501587f8160864815c07ac to your computer and use it in GitHub Desktop.
Save kbrock/978baec148501587f8160864815c07ac to your computer and use it in GitHub Desktop.
Performance comparison of different ruby serializer methods
gem
Json oj 40.4 i/s
MessagePack 38.3 i/s same
binary json 22.0 i/s 1.84x slower
Json yajl 19.0 i/s 2.13x slower
ruby json 15.6 i/s 2.59x slower
ruby marshal 13.9 i/s 2.90x slower
ruby yaml 0.4 i/s 111.99x slower
Yaml Psych 0.4 i/s 112.09x slower
ruby safe 0.4 i/s 113.66x slower
-- primitives only
marshal -- true
"\x04\b{\tI\"\tname\x06:\x06ETI\"\x13Fredrick Smith\x06;\x00TI\"\rquantity\x06;\x00Ti\x03@B\x0FI\"\tdate\x06;\x00TI\"\x1E2017-08-11 11:17:00 -0400\x06;\x00FI\"\x0Eaddresses\x06;\x00T{\aI\"\raddress1\x06;\x00TI\"612 Heather Street, Parnell, Auckland, New Zealand\x06;\x00TI\"\raddress2\x06;\x00TI\"/1 Queen Street, CBD, Auckland, New Zealand\x06;\x00T"
bson -- true
"\xD9\x00\x00\x00\x02name\x00\x0F\x00\x00\x00Fredrick Smith\x00\x10quantity\x00@B\x0F\x00\x02date\x00\x1A\x00\x00\x002017-08-11 11:17:00 -0400\x00\x03addresses\x00~\x00\x00\x00\x02address1\x002\x00\x00\x0012 Heather Street, Parnell, Auckland, New Zealand\x00\x02address2\x00+\x00\x00\x001 Queen Street, CBD, Auckland, New Zealand\x00\x00\x00"
msgpack -- true
"\x84\xA4name\xAEFredrick Smith\xA8quantity\xCE\x00\x0FB@\xA4date\xB92017-08-11 11:17:00 -0400\xA9addresses\x82\xA8address1\xD9112 Heather Street, Parnell, Auckland, New Zealand\xA8address2\xD9*1 Queen Street, CBD, Auckland, New Zealand"
json -- true
"{\"name\":\"Fredrick Smith\",\"quantity\":1000000,\"date\":\"2017-08-11 11:17:00 -0400\",\"addresses\":{\"address1\":\"12 Heather Street, Parnell, Auckland, New Zealand\",\"address2\":\"1 Queen Street, CBD, Auckland, New Zealand\"}}"
yajl -- true
"{\"name\":\"Fredrick Smith\",\"quantity\":1000000,\"date\":\"2017-08-11 11:17:00 -0400\",\"addresses\":{\"address1\":\"12 Heather Street, Parnell, Auckland, New Zealand\",\"address2\":\"1 Queen Street, CBD, Auckland, New Zealand\"}}"
oj -- true
"{\"name\":\"Fredrick Smith\",\"quantity\":1000000,\"date\":\"2017-08-11 11:17:00 -0400\",\"addresses\":{\"address1\":\"12 Heather Street, Parnell, Auckland, New Zealand\",\"address2\":\"1 Queen Street, CBD, Auckland, New Zealand\"}}"
yaml -- true
"---\nname: Fredrick Smith\nquantity: 1000000\ndate: '2017-08-11 11:17:00 -0400'\naddresses:\n address1: 12 Heather Street, Parnell, Auckland, New Zealand\n address2: 1 Queen Street, CBD, Auckland, New Zealand\n"
psych -- true
"---\nname: Fredrick Smith\nquantity: 1000000\ndate: '2017-08-11 11:17:00 -0400'\naddresses:\n address1: 12 Heather Street, Parnell, Auckland, New Zealand\n address2: 1 Queen Street, CBD, Auckland, New Zealand\n"
safe -- true
"---\nname: Fredrick Smith\nquantity: 1000000\ndate: '2017-08-11 11:17:00 -0400'\naddresses:\n address1: 12 Heather Street, Parnell, Auckland, New Zealand\n address2: 1 Queen Street, CBD, Auckland, New Zealand\n"
-----
- symbol and date thrown in there
marshal -- true
"\x04\b{\t:\tnameI\"\x13Fredrick Smith\x06:\x06ET:\rquantityi\x03@B\x0F:\tdateIu:\tTime\ro]\x1D\x80\xF5\x00$U\a:\voffseti\xFE\xC0\xC7:\tzoneI\"\bEDT\x06;\x06F:\x0Eaddresses{\a:\raddress1I\"612 Heather Street, Parnell, Auckland, New Zealand\x06;\x06T:\raddress2I\"/1 Queen Street, CBD, Auckland, New Zealand\x06;\x06T"
bson -- false
"\xC3\x00\x00\x00\x02name\x00\x0F\x00\x00\x00Fredrick Smith\x00\x10quantity\x00@B\x0F\x00\tdate\x00\xB6\xA6\xE2\xD1]\x01\x00\x00\x03addresses\x00~\x00\x00\x00\x02address1\x002\x00\x00\x0012 Heather Street, Parnell, Auckland, New Zealand\x00\x02address2\x00+\x00\x00\x001 Queen Street, CBD, Auckland, New Zealand\x00\x00\x00"
msgpack -- ERROR
json -- false
"{\"name\":\"Fredrick Smith\",\"quantity\":1000000,\"date\":\"2017-08-11 11:21:18 -0400\",\"addresses\":{\"address1\":\"12 Heather Street, Parnell, Auckland, New Zealand\",\"address2\":\"1 Queen Street, CBD, Auckland, New Zealand\"}}"
yajl -- false
"{\"name\":\"Fredrick Smith\",\"quantity\":1000000,\"date\":\"2017-08-11 11:21:18 -0400\",\"addresses\":{\"address1\":\"12 Heather Street, Parnell, Auckland, New Zealand\",\"address2\":\"1 Queen Street, CBD, Auckland, New Zealand\"}}"
oj -- true
"{\":name\":\"Fredrick Smith\",\":quantity\":1000000,\":date\":{\"^t\":1502464878.262389000},\":addresses\":{\":address1\":\"12 Heather Street, Parnell, Auckland, New Zealand\",\":address2\":\"1 Queen Street, CBD, Auckland, New Zealand\"}}"
yaml -- true
"---\n:name: Fredrick Smith\n:quantity: 1000000\n:date: 2017-08-11 11:21:18.262389000 -04:00\n:addresses:\n :address1: 12 Heather Street, Parnell, Auckland, New Zealand\n :address2: 1 Queen Street, CBD, Auckland, New Zealand\n"
psych -- true
"---\n:name: Fredrick Smith\n:quantity: 1000000\n:date: 2017-08-11 11:21:18.262389000 -04:00\n:addresses:\n :address1: 12 Heather Street, Parnell, Auckland, New Zealand\n :address2: 1 Queen Street, CBD, Auckland, New Zealand\n"
safe -- ERROR
#!/usr/bin/env ruby
# gem install bson
# gem install bson_ext
# gem install yajl-ruby
# gem install json
# gem install msgpack
# gem install oj
# gem install psych
# gem install benchmark-ips
require 'benchmark/ips'
require 'rubygems'
require 'benchmark'
require 'yaml' # ruby yaml -- handles dates
require 'bson' # binary json
require 'json' # ruby json
require 'yajl' # json
require 'msgpack' # binary serializer
require 'oj' # json -- handles dates
require 'psych' # yaml -- handles dates
require 'optparse'
binary = false
mode = :bmbm
OptionParser.new do |opt|
opt.on('-b', '--binary', "binary data") { |v| binary = v}
opt.on('-i', '--ips', "ips") { mode = :ips }
opt.parse!(ARGV)
end
METHODS = {
:marshal => { :verbose => "ruby marshal", :encoder => -> (msg) { Marshal.dump(msg) }, :decoder => -> (str) { Marshal.load(str) } },
:bson => { :verbose => "binary json", :encoder => -> (msg) { msg.to_bson }, :decoder => -> (str) { Hash.from_bson(str) } },
:msgpack => { :verbose => "MessagePack", :encoder => -> (msg) { MessagePack.pack(msg) }, :decoder => -> (str) { MessagePack.unpack(str) } },
:yaml => { :verbose => "ruby yaml", :encoder => -> (msg) { msg.to_yaml}, :decoder => -> (str) { YAML.load(str) } },
:safe => { :verbose => "ruby safe", :encoder => -> (msg) { msg.to_yaml}, :decoder => -> (str) { YAML.safe_load(str) } },
:psych => { :verbose => "Yaml Psych", :encoder => -> (msg) { Psych.dump(msg) }, :decoder => -> (str) { Psych.load(str) } },
:json => { :verbose => "ruby json", :encoder => -> (msg) { JSON.generate(msg) }, :decoder => -> (str) { JSON.parse(str) } },
:yajl => { :verbose => "Json yajl", :encoder => -> (msg) { Yajl::Encoder.encode(msg) }, :decoder => -> (str) { Yajl::Parser.parse(str) } },
:oj => { :verbose => "Json oj", :encoder => -> (msg) { Oj.dump(msg) }, :decoder => -> (str) { Oj.load(str) } },
}
SAMPLES = 5_000
obj = if binary
{
:name => "Fredrick Smith",
:quantity => 1_000_000,
:date => Time.now,
:addresses => {
:address1 => "12 Heather Street, Parnell, Auckland, New Zealand",
:address2 => "1 Queen Street, CBD, Auckland, New Zealand"
}
}
else
{
"name" => "Fredrick Smith",
"quantity" => 1_000_000,
"date" => Time.now.to_s,
"addresses" => {
"address1" => "12 Heather Street, Parnell, Auckland, New Zealand",
"address2" => "1 Queen Street, CBD, Auckland, New Zealand"
}
}
end
Benchmark.send(mode) do |r|
METHODS.each do |method, options|
begin
encoder = options[:encoder]
decoder = options[:decoder]
same = (obj == decoder.call(encoder.call(obj)))
# puts(encoder.call(obj).to_s.inspect)
r.report("#{options[:verbose]} (#{same})") do
SAMPLES.times do
decoder.call(encoder.call(obj))
end
end
rescue
puts "#{method} -- ERROR"
end
end
r.compare! if mode == :ips
end
# Results
# -------
# user system total real
# marshal 0.070000 0.000000 0.070000 ( 0.068565)
# bson 0.050000 0.000000 0.050000 ( 0.049747)
# msgpack 0.030000 0.000000 0.030000 ( 0.023521)
# json 0.060000 0.000000 0.060000 ( 0.061108)
# yajl 0.050000 0.000000 0.050000 ( 0.051075)
# oj 0.020000 0.000000 0.020000 ( 0.022084)
# yaml 2.660000 0.030000 2.690000 ( 2.691348)
# psych 2.640000 0.030000 2.670000 ( 2.665381)
# safe 2.680000 0.030000 2.710000 ( 2.715144)
@michaelglass
Copy link

michaelglass commented Aug 29, 2017

my results against ruby 2.3.3, from fastest -> slowest

Rehearsal -------------------------------------------------------
Json oj (true)        0.030000   0.000000   0.030000 (  0.033081)
MessagePack (true)    0.030000   0.010000   0.040000 (  0.046553)
binary json (true)    0.060000   0.000000   0.060000 (  0.055872)
ruby json (true)      0.060000   0.000000   0.060000 (  0.065484)
Json yajl (true)      0.070000   0.010000   0.080000 (  0.086215)
ruby marshal (true)   0.080000   0.000000   0.080000 (  0.088573)
ruby safe (true)      2.590000   0.040000   2.630000 (  2.624692)
Yaml Psych (true)     2.590000   0.040000   2.630000 (  2.636381)
ruby yaml (true)      2.610000   0.040000   2.650000 (  2.671206)
---------------------------------------------- total: 8.260000sec

                          user     system      total        real
Json oj (true)        0.040000   0.000000   0.040000 (  0.034682)
MessagePack (true)    0.030000   0.000000   0.030000 (  0.044521)
binary json (true)    0.050000   0.000000   0.050000 (  0.054218)
Json yajl (true)      0.060000   0.010000   0.070000 (  0.076914)
ruby json (true)      0.080000   0.000000   0.080000 (  0.086154)
ruby marshal (true)   0.090000   0.000000   0.090000 (  0.092348)
Yaml Psych (true)     2.660000   0.020000   2.680000 (  2.701861)
ruby safe (true)      2.690000   0.030000   2.720000 (  2.732333)
ruby yaml (true)      2.690000   0.030000   2.720000 (  2.746539)

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