intridea/multi_json — pull request #146 by grddev (2014-04-30 12:18:51+00:00)
Title: Performance tweaks

After noticing that selecting the right adaptor and options (which did not change over multiple uses of `MultiJson.dump`) was actually dominating the CPU resources used in my JRuby application I implemented a small benchmark and implemented various tweaks to improve the performance.

Here is my benchmark.rb:

require 'benchmark'
require 'json'
require 'multi_json'

OBJECT = { a: 'b', c: 1, d: 1.0, e: [nil, true, false] }
N = 100_000

Benchmark.bmbm do |x|
x.report('common') { N.times { OBJECT.to_json } }
x.report('multi1') { N.times { MultiJson.dump(OBJECT) } }
x.report('multi2') { N.times { MultiJson.adapter.dump(OBJECT) } }
end

With this I get some performance boost in ruby-2.1.1, (master results results above, my branch below):

user system total real
common 0.860000 0.000000 0.860000 ( 0.865212)
multi1 1.800000 0.000000 1.800000 ( 1.812002)
multi2 1.770000 0.010000 1.780000 ( 1.778864)

user system total real
common 0.870000 0.000000 0.870000 ( 0.871332)
multi1 1.280000 0.000000 1.280000 ( 1.281935)
multi2 1.270000 0.010000 1.280000 ( 1.273005)

which means going from around 110% overhead compared to plain `.to_json` down to about 50%. However, the results are even nicer for JRuby (once again master results above, my branch below)

user system total real
common 1.160000 0.000000 1.160000 ( 1.160000)
multi1 3.520000 0.020000 3.540000 ( 3.535000)
multi2 3.360000 0.010000 3.370000 ( 3.371000)

user system total real
common 1.040000 0.010000 1.050000 ( 1.046000)
multi1 1.960000 0.000000 1.960000 ( 1.959000)
multi2 1.830000 0.010000 1.840000 ( 1.845000)

which means going from a 220% overhead down about 90% overhead compared to plain `.to_json`.

As this completely removes the cache it obviously breaks the `MultiJson.cached_options` interface, but I'm guessing that was never (meant to be) public, so I'm guessing this should not be a problem.

It also breaks the inheritance interface for adapters as it removes a bunch of protected methods, but hopefully that wasn't meant as a public interface either.