Performance comparison of different ruby serializer methods
2.5.0 |
require './serializer_benchmarks' | |
hash = { | |
'name' => 'Fredrick Smith', | |
'quantity' => 1_000_000, | |
'addresses' => { | |
'address1' => '12 Heather Street, Parnell, Auckland, New Zealand', | |
'address2' => '1 Queen Street, CBD, Auckland, New Zealand' | |
} | |
} | |
run(hash) | |
run('string') | |
run(3.4) | |
run(nil) | |
run(true) |
GEM | |
remote: https://rubygems.org/ | |
specs: | |
benchmark-ips (2.7.2) | |
bson (4.3.0) | |
json (2.1.0) | |
msgpack (1.2.4) | |
oj (3.5.0) | |
yajl-ruby (1.3.1) | |
PLATFORMS | |
ruby | |
DEPENDENCIES | |
benchmark-ips | |
bson | |
json | |
msgpack | |
oj | |
yajl-ruby | |
BUNDLED WITH | |
1.16.1 |
require './serializer_benchmarks' | |
hash = { | |
'name' => 'Fredrick Smith', | |
'quantity' => 1_000_000, | |
'addresses' => { | |
'address1' => '12 Heather Street, Parnell, Auckland, New Zealand', | |
'address2' => '1 Queen Street, CBD, Auckland, New Zealand' | |
} | |
} | |
class CustomClass | |
attr_accessor :variable | |
def run(a, b) | |
a + b | |
end | |
def ==(other_custom_class) | |
self.variable == other_custom_class.variable | |
end | |
end | |
custom_class = CustomClass.new.tap { |instance| instance.variable = 'value' } | |
benches = DEFAULT_BENCHES.slice(:marshal, :oj) | |
run(hash, benches) | |
run(custom_class, benches) | |
run('string', benches) | |
run(3.4, benches) | |
run(3, benches) | |
run(nil, benches) | |
run(true, benches) |
# Intel(R) Core(TM) i7-7600U CPU @ 2.80GHz, 16GB DDR3 RAM | |
# ruby 2.5.0 | |
# all_with_hash.rb | |
--> Benchmarking an object of type Hash | |
JSON (using oj): 68.3 i/s | |
MessagePack: 62.7 i/s - 1.09x slower | |
BSON: 54.7 i/s - 1.25x slower | |
Marshal: 41.4 i/s - 1.65x slower | |
JSON (using Yajl): 31.3 i/s - 2.18x slower | |
JSON (built-in ruby): 26.9 i/s - 2.54x slower | |
YAML: 1.2 i/s - 59.15x slower | |
--> Benchmarking an object of type String | |
JSON (using oj): 344.6 i/s | |
BSON: 308.3 i/s - 1.12x slower | |
Marshal: 151.1 i/s - 2.28x slower | |
MessagePack: 127.8 i/s - 2.70x slower | |
JSON (built-in ruby): 99.2 i/s - 3.47x slower | |
JSON (using Yajl): 96.9 i/s - 3.55x slower | |
YAML: 4.7 i/s - 74.01x slower | |
--> Benchmarking an object of type Float | |
BSON: 332.6 i/s | |
JSON (using oj): 204.1 i/s - 1.63x slower | |
Marshal: 168.1 i/s - 1.98x slower | |
MessagePack: 124.3 i/s - 2.68x slower | |
JSON (built-in ruby): 83.8 i/s - 3.97x slower | |
JSON (using Yajl): 80.2 i/s - 4.15x slower | |
YAML: 4.5 i/s - 73.27x slower | |
# reduced_with_different_objects.rb | |
--> Benchmarking an object of type Float | |
JSON (using oj): 198.8 i/s | |
Marshal: 169.1 i/s - 1.18x slower | |
--> Benchmarking an object of type Hash | |
JSON (using oj): 70.9 i/s | |
Marshal: 44.4 i/s - 1.60x slower | |
--> Benchmarking an object of type String | |
JSON (using oj): 368.0 i/s | |
Marshal: 158.3 i/s - 2.33x slower | |
--> Benchmarking an object of type CustomClass | |
JSON (using oj): 195.2 i/s | |
Marshal: 87.4 i/s - 2.23x slower |
require 'benchmark/ips' | |
require 'bson' | |
require 'json' | |
require 'msgpack' | |
require 'oj' | |
require 'yajl' | |
require 'yaml' | |
SAMPLES = 5_000 | |
DEFAULT_BENCHES = { | |
marshal: 'Marshal', | |
json: 'JSON (built-in ruby)', | |
yajl: 'JSON (using Yajl)', | |
oj: 'JSON (using oj)', | |
bson: 'BSON', | |
yaml: 'YAML', | |
msgpack: 'MessagePack' | |
}.freeze | |
def encode(msg, format) | |
case format | |
when :yaml | |
msg.to_yaml | |
when :marshal | |
Marshal.dump(msg) | |
when :json | |
JSON.generate(msg) | |
when :yajl | |
Yajl::Encoder.encode(msg) | |
when :oj | |
Oj.dump(msg) | |
when :bson | |
msg.to_bson | |
when :msgpack | |
MessagePack.pack(msg) | |
end | |
end | |
def decode(str, format, type) | |
case format | |
when :yaml | |
YAML.load(str) | |
when :marshal | |
Marshal.load(str) | |
when :json | |
JSON.parse(str) | |
when :yajl | |
Yajl::Parser.parse(str) | |
when :oj | |
Oj.load(str) | |
when :bson | |
type.from_bson(str) | |
when :msgpack | |
MessagePack.unpack(str) | |
end | |
end | |
def run(obj, benches = DEFAULT_BENCHES) | |
puts "--> Benchmarking an object of type #{obj.class}" | |
Benchmark.ips do |r| | |
benches.each do |key, title| | |
r.report(title) do | |
SAMPLES.times do | |
decoded_obj = decode(encode(obj, key), key, obj.class) | |
if decoded_obj != obj | |
raise <<~RAISE | |
Deserialized object of type #{obj.class} is not the same as before serialization / deserialization | |
before: #{obj.inspect} | |
after: #{decoded_obj.inspect} | |
RAISE | |
end | |
end | |
end | |
end | |
r.compare! | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment