├── .gitignore ├── Gemfile ├── gemfiles ├── 4.0.13.gemfile ├── 4.1.16.gemfile ├── 4.2.8.gemfile ├── 5.0.2.gemfile ├── 3.2.22.5.gemfile ├── 4.1.16.gemfile.lock ├── 4.2.8.gemfile.lock └── 5.0.2.gemfile.lock ├── .travis.yml ├── lib ├── helper_msgpack.rb ├── msg_pack_rails_compat.rb ├── test_data_rails.rb ├── test_data_json.rb └── helper.rb ├── update_bundle.sh ├── rails_benchmark.rb ├── benchmark.rb ├── compatibility_test.rb ├── Gemfile.lock ├── README.md └── test_report.txt /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | gemfiles/.bundle 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "wwtd" 4 | 5 | # TODO remove 6 | gem "rails", "4.1.16" 7 | gem "sqlite3" 8 | gem "benchmark-memory" 9 | gem "oj", ">= 3.0.2" 10 | gem "terminal-table" 11 | gem "msgpack" 12 | -------------------------------------------------------------------------------- /gemfiles/4.0.13.gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "rails", "4.0.13" 4 | gem "sqlite3" 5 | gem "benchmark-memory" 6 | gem "benchmark-ips" 7 | 8 | gem "oj", ">= 3.0.6" 9 | gem "terminal-table" 10 | gem "msgpack" 11 | -------------------------------------------------------------------------------- /gemfiles/4.1.16.gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "rails", "4.1.16" 4 | gem "sqlite3" 5 | gem "benchmark-memory" 6 | gem "benchmark-ips" 7 | 8 | gem "oj", ">= 3.0.6" 9 | gem "terminal-table" 10 | gem "msgpack" 11 | -------------------------------------------------------------------------------- /gemfiles/4.2.8.gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "rails", "4.2.8" 4 | gem "sqlite3" 5 | gem "benchmark-memory" 6 | gem "benchmark-ips" 7 | 8 | gem "oj", ">= 3.0.6" 9 | gem "terminal-table" 10 | gem "msgpack" 11 | -------------------------------------------------------------------------------- /gemfiles/5.0.2.gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "rails", "5.0.2" 4 | gem "sqlite3" 5 | gem "benchmark-memory" 6 | gem "benchmark-ips" 7 | 8 | gem "oj", ">= 3.0.6" 9 | gem "terminal-table" 10 | gem "msgpack" 11 | -------------------------------------------------------------------------------- /gemfiles/3.2.22.5.gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "rails", "3.2.22.5" 4 | gem "sqlite3" 5 | gem "benchmark-memory" 6 | gem "benchmark-ips" 7 | 8 | gem "oj", ">= 3.0.6" 9 | gem "terminal-table" 10 | gem "msgpack" 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | langauge: ruby 2 | sudo: false 3 | cache: bundler 4 | 5 | branches: 6 | only: master 7 | 8 | script: bundle exec ruby compatibility_test.rb && bundle exec ruby benchmark.rb 9 | # bundle exec ruby rails_benchmark.rb 10 | 11 | rvm: 12 | - 2.2.6 13 | - 2.3.3 14 | - 2.4.0 15 | 16 | gemfile: 17 | - gemfiles/4.1.16.gemfile 18 | - gemfiles/4.2.8.gemfile 19 | - gemfiles/5.0.2.gemfile 20 | 21 | matrix: 22 | fast_finish: true 23 | -------------------------------------------------------------------------------- /lib/helper_msgpack.rb: -------------------------------------------------------------------------------- 1 | require_relative './msg_pack_rails_compat' 2 | 3 | def test_msgpack(test_data, test_result, implementation, implementation_compare) 4 | test_data.each do |key, val| 5 | test_result[key] ||= {} 6 | from_json = ActiveSupport::JSON.decode(test_result[key][implementation_compare]) 7 | from_msgpack = begin 8 | res = MessagePack.pack(val) 9 | MessagePack.unpack(res) 10 | rescue StandardError => e 11 | e 12 | end 13 | test_result[key][implementation] = compare(from_json, from_msgpack) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/msg_pack_rails_compat.rb: -------------------------------------------------------------------------------- 1 | require 'msgpack' 2 | 3 | class Object 4 | def to_msgpack_rails(options = nil) #:nodoc: 5 | as_json(options).to_msgpack 6 | end 7 | def from_msgpack_rails(value) #:nodoc: 8 | MessagePack.unpack(value) 9 | end 10 | end 11 | 12 | # class Float 13 | # alias_method :to_msgpack_native, :to_msgpack 14 | 15 | # def to_msgpack(options = nil) #:nodoc: 16 | # if self.infinite? 17 | # nil.to_msgpack 18 | # else 19 | # to_msgpack_native 20 | # end 21 | # end 22 | # end 23 | 24 | MessagePack::DefaultFactory.register_type(0x01, Object, packer: :to_msgpack_rails, unpacker: :from_msgpack_rails) 25 | -------------------------------------------------------------------------------- /update_bundle.sh: -------------------------------------------------------------------------------- 1 | # rbenv local 2.2.6 2 | # gem install bundler 3 | # rbenv local 2.3.3 4 | # gem install bundler 5 | # rbenv local 2.4.0 6 | # gem install bundler 7 | # rbenv local --unset 8 | 9 | rm -rf gemfiles/.bundle 10 | BUNDLE_GEMFILE=gemfiles/4.1.16.gemfile RBENV_VERSION=2.2.6 bundle 11 | rm -rf gemfiles/.bundle 12 | BUNDLE_GEMFILE=gemfiles/4.1.16.gemfile RBENV_VERSION=2.3.3 bundle 13 | rm -rf gemfiles/.bundle 14 | BUNDLE_GEMFILE=gemfiles/4.1.16.gemfile RBENV_VERSION=2.4.0 bundle 15 | rm -rf gemfiles/.bundle 16 | BUNDLE_GEMFILE=gemfiles/4.2.8.gemfile RBENV_VERSION=2.2.6 bundle 17 | rm -rf gemfiles/.bundle 18 | BUNDLE_GEMFILE=gemfiles/4.2.8.gemfile RBENV_VERSION=2.3.3 bundle 19 | rm -rf gemfiles/.bundle 20 | BUNDLE_GEMFILE=gemfiles/4.2.8.gemfile RBENV_VERSION=2.4.0 bundle 21 | rm -rf gemfiles/.bundle 22 | BUNDLE_GEMFILE=gemfiles/5.0.2.gemfile RBENV_VERSION=2.2.6 bundle 23 | rm -rf gemfiles/.bundle 24 | BUNDLE_GEMFILE=gemfiles/5.0.2.gemfile RBENV_VERSION=2.3.3 bundle 25 | rm -rf gemfiles/.bundle 26 | BUNDLE_GEMFILE=gemfiles/5.0.2.gemfile RBENV_VERSION=2.4.0 bundle 27 | -------------------------------------------------------------------------------- /rails_benchmark.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require 'benchmark/memory' 3 | require 'benchmark/ips' 4 | 5 | require 'json/add/complex' 6 | require 'json/add/rational' 7 | 8 | require './lib/test_data_json' 9 | require './lib/test_data_rails' 10 | 11 | obj = TEST_DATA_JSON.merge(TEST_DATA_RAILS) 12 | obj.delete(:'ActiveModel::Errors') 13 | obj.delete(:'ActiveRecord::Relation') 14 | obj.delete(:'ActiveRecord') 15 | # obj.delete(:Complex) 16 | 17 | puts "Rails" 18 | 19 | Benchmark.memory do |x| 20 | x.report('to_json') { 10_000.times { obj.to_json } } 21 | end 22 | 23 | puts "---------------------------------------------\n\n" 24 | 25 | Benchmark.ips do |x| 26 | x.report('to_json') { obj.to_json } 27 | end 28 | 29 | puts "\n with Oj" 30 | 31 | require 'oj' 32 | Oj.optimize_rails() 33 | Oj.add_to_json(Rational, Complex) 34 | 35 | Benchmark.memory do |x| 36 | x.report('to_json') { 10_000.times { obj.to_json } } 37 | end 38 | 39 | puts "---------------------------------------------\n\n" 40 | 41 | Benchmark.ips do |x| 42 | x.report('to_json') { obj.to_json } 43 | end 44 | -------------------------------------------------------------------------------- /lib/test_data_rails.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require 'rails/all' 3 | require 'sqlite3' 4 | 5 | ENV['RAILS_ENV'] = 'production' 6 | ActiveRecord::Base.logger = Logger.new(STDERR) 7 | ActiveRecord::Base.logger.level = 1 8 | ActiveRecord::Migration.verbose = false 9 | 10 | ActiveRecord::Base.establish_connection( 11 | adapter: 'sqlite3', 12 | database:':memory:' 13 | ) 14 | ActiveRecord::Schema.define do 15 | create_table :users do |table| 16 | table.column :name, :string 17 | end 18 | end 19 | 20 | class User < ActiveRecord::Base 21 | validates :name, presence: true 22 | end 23 | 24 | user = User.new 25 | user.valid? 26 | 27 | TEST_DATA_RAILS = { 28 | 'ActiveSupport::TimeWithZone': Time.utc(2005,2,1,15,15,10).in_time_zone('Hawaii'), 29 | 'ActiveModel::Errors': user.errors, 30 | 'ActiveSupport::Duration': 1.month.ago, 31 | 'ActiveSupport::Multibyte::Chars': 'über'.mb_chars, 32 | 'ActiveRecord::Relation': User.where(name: 'aaa'), 33 | 'ActiveRecord': User.find_or_create_by(name: "John") 34 | # 'ActionDispatch::Journey::GTG::TransitionTable': TODO, 35 | } 36 | -------------------------------------------------------------------------------- /benchmark.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'json/add/complex' 4 | require 'json/add/rational' 5 | OJ_RAILS = { mode: :rails, use_to_json: true }.freeze 6 | 7 | require './lib/test_data_json' 8 | require './lib/test_data_rails' 9 | 10 | require 'oj' 11 | require './lib/msg_pack_rails_compat' 12 | 13 | require 'benchmark/memory' 14 | require 'benchmark/ips' 15 | 16 | obj = TEST_DATA_JSON.merge(TEST_DATA_RAILS) 17 | obj.delete(:'ActiveModel::Errors') 18 | obj.delete(:'ActiveRecord::Relation') 19 | obj.delete(:'ActiveRecord') 20 | # obj.delete(:AsJson) 21 | # obj.delete(:ToJson) 22 | # obj.delete(:Complex) 23 | 24 | Oj::Rails.optimize(Array, BigDecimal, Hash, Range, Regexp, Time, ActiveSupport::TimeWithZone) 25 | Oj.add_to_json(Rational, Complex) 26 | 27 | puts "\n" 28 | 29 | Benchmark.memory do |x| 30 | x.report('Rails to_json') { 10_000.times { obj.to_json } } 31 | x.report('msgpack') { 10_000.times { MessagePack.pack(obj) } } 32 | x.report('Oj.dump') { 10_000.times { Oj.dump(obj, OJ_RAILS) } } 33 | x.report('Oj::Rails.encode') { 10_000.times { Oj::Rails.encode(obj) } } 34 | x.compare! 35 | end 36 | 37 | puts "---------------------------------------------\n\n" 38 | 39 | Benchmark.ips do |x| 40 | x.report('Rails to_json') { obj.to_json } 41 | x.report('msgpack') { MessagePack.pack(obj) } 42 | x.report('Oj.dump') { Oj.dump(obj, OJ_RAILS) } 43 | x.report('Oj::Rails.encode') { Oj::Rails.encode(obj) } 44 | x.compare! 45 | end 46 | 47 | puts "\n" 48 | -------------------------------------------------------------------------------- /lib/test_data_json.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require 'bigdecimal' 3 | require 'bigdecimal/util' 4 | require 'date' 5 | require 'ostruct' 6 | 7 | class Colors 8 | include Enumerable 9 | def each 10 | yield 'red' 11 | yield 'green' 12 | yield 'blue' 13 | end 14 | end 15 | 16 | Struct.new('Customer', :name, :address) 17 | 18 | fork { exit 99 } 19 | Process.wait 20 | 21 | class AsJson 22 | def as_json(options = nil) 23 | {a: 1} 24 | end 25 | end 26 | 27 | class ToJson 28 | def to_json(options = nil) 29 | '{"a":1}' 30 | end 31 | end 32 | 33 | TEST_DATA_JSON = { 34 | Regexp: /test/, 35 | FalseClass: false, 36 | NilClass: nil, 37 | Object: Object.new, 38 | TrueClass: true, 39 | String: 'abc', 40 | StringChinese: '二胡', 41 | StringSpecial: "\u2028\u2029><&", 42 | StringSpecial2: "\/", 43 | StringSpecial3: "\\\b\f\n\r\t", 44 | Numeric: 1, 45 | Symbol: :sym, 46 | Time: Time.new(2012, 1, 5, 23, 58, 7.99996, 32400), 47 | Array: [], 48 | Hash: {}, 49 | HashNotEmpty: {a: 1}, 50 | Date: Date.new, 51 | DateTime: DateTime.new, 52 | Enumerable: Colors.new, 53 | BigDecimal: '1'.to_d/3, 54 | BigDecimalInfinity: '0.5'.to_d/0, 55 | Struct: Struct::Customer.new('Dave', '123 Main'), 56 | Float: 1.0/3, 57 | FloatInfinity: 0.5/0, 58 | Range: (1..10), 59 | Complex: Complex('0.3-0.5i'), 60 | Exception: Exception.new, 61 | OpenStruct: OpenStruct.new(:country => "Australia", :population => 20_000_000), 62 | Rational: Rational(0.3), 63 | 'Process::Status': $?, 64 | AsJson: AsJson.new, 65 | ToJson: ToJson.new 66 | } 67 | -------------------------------------------------------------------------------- /compatibility_test.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require './lib/helper' 3 | require './lib/test_data_json' 4 | 5 | test_result = {} 6 | 7 | test_to_json(TEST_DATA_JSON, test_result, :json_gem) 8 | test_json_generate(TEST_DATA_JSON, test_result, :json_generate) 9 | 10 | require './lib/test_data_rails' 11 | 12 | test_to_json(TEST_DATA_JSON, test_result, :rails) 13 | test_to_json(TEST_DATA_RAILS, test_result, :rails) 14 | 15 | test_json_generate(TEST_DATA_RAILS, test_result, :json_generate) 16 | 17 | require './lib/helper_msgpack' 18 | 19 | test_msgpack(TEST_DATA_JSON, test_result, :msgpack, :rails) 20 | test_msgpack(TEST_DATA_RAILS, test_result, :msgpack, :rails) 21 | 22 | Oj::Rails.set_encoder() 23 | Oj::Rails.set_decoder() 24 | Oj::Rails.optimize(Array, BigDecimal, Hash, Range, Regexp, Time) # DateTime doesn't work 25 | Oj.add_to_json(Rational, Complex) 26 | 27 | test_to_json(TEST_DATA_JSON, test_result, :oj_to_json) 28 | test_to_json(TEST_DATA_RAILS, test_result, :oj_to_json) 29 | 30 | test_oj_dump(TEST_DATA_JSON, test_result, :oj_dump) 31 | test_oj_dump(TEST_DATA_RAILS, test_result, :oj_dump) 32 | 33 | test_oj_rails(TEST_DATA_JSON, test_result, :oj_rails) 34 | test_oj_rails(TEST_DATA_RAILS, test_result, :oj_rails) 35 | 36 | # NOTE: 37 | # JSON.generate in quirks mode equal to Obj.to_json from JSON gem 38 | # Oj.dump(val, mode: :rails) seems to be the same as Oj::Rails.encode(val) 39 | rows = test_result.map do |key, val| 40 | [key, 41 | compare(val[:rails], val[:json_gem]), 42 | compare(val[:rails], val[:oj_dump]), 43 | compare(val[:rails], val[:oj_rails]), 44 | compare(val[:rails], val[:oj_to_json]), 45 | val[:msgpack] 46 | ] 47 | end 48 | 49 | require 'terminal-table' 50 | puts "\nComparing Rails to_json with other JSON implementations\n" 51 | puts Terminal::Table.new headings: ['class', 'JSON to_json', 'Oj.dump', 'Oj::Rails.encode', 'Oj to_json', 'msgpack "rails"'], rows: rows 52 | -------------------------------------------------------------------------------- /lib/helper.rb: -------------------------------------------------------------------------------- 1 | require 'oj' 2 | require 'json' 3 | 4 | # this required for msgpack compatibility test 5 | require 'json/add/complex' 6 | require 'json/add/rational' 7 | 8 | def compare(expected, result) 9 | if result.is_a? Exception 10 | '💀' 11 | else 12 | expected == result ? '👌' : '❌' 13 | end 14 | end 15 | 16 | # def compare(expected, result) 17 | # if result.is_a? Exception 18 | # 'Error' 19 | # else 20 | # expected == result ? 'Ok' : 'Fail' 21 | # end 22 | # end 23 | 24 | def test_to_json(test_data, test_result, implementation) 25 | test_data.each do |key, val| 26 | test_result[key] ||= {} 27 | test_result[key][implementation] = begin 28 | val.to_json 29 | rescue JSON::GeneratorError => e 30 | e 31 | end 32 | end 33 | end 34 | 35 | def test_json_generate(test_data, test_result, implementation) 36 | test_data.each do |key, val| 37 | test_result[key] ||= {} 38 | test_result[key][implementation] = begin 39 | JSON.generate(val, quirks_mode: true) 40 | rescue JSON::GeneratorError => e 41 | e 42 | end 43 | end 44 | end 45 | 46 | OJ_RAILS = {mode: :rails, use_to_json: true}.freeze 47 | def test_oj_dump(test_data, test_result, implementation) 48 | test_data.each do |key, val| 49 | test_result[key] ||= {} 50 | test_result[key][implementation] = begin 51 | Oj.dump(val, OJ_RAILS) 52 | rescue NoMemoryError => e 53 | e 54 | rescue NotImplementedError => e 55 | e 56 | rescue EncodingError => e 57 | e 58 | rescue RuntimeError => e 59 | e 60 | end 61 | end 62 | end 63 | 64 | def test_oj_rails(test_data, test_result, implementation) 65 | test_data.each do |key, val| 66 | test_result[key] ||= {} 67 | test_result[key][implementation] = begin 68 | Oj::Rails.encode(val) 69 | rescue NoMemoryError => e 70 | e 71 | rescue NotImplementedError => e 72 | e 73 | rescue EncodingError => e 74 | e 75 | rescue RuntimeError => e 76 | e 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /gemfiles/4.1.16.gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | actionmailer (4.1.16) 5 | actionpack (= 4.1.16) 6 | actionview (= 4.1.16) 7 | mail (~> 2.5, >= 2.5.4) 8 | actionpack (4.1.16) 9 | actionview (= 4.1.16) 10 | activesupport (= 4.1.16) 11 | rack (~> 1.5.2) 12 | rack-test (~> 0.6.2) 13 | actionview (4.1.16) 14 | activesupport (= 4.1.16) 15 | builder (~> 3.1) 16 | erubis (~> 2.7.0) 17 | activemodel (4.1.16) 18 | activesupport (= 4.1.16) 19 | builder (~> 3.1) 20 | activerecord (4.1.16) 21 | activemodel (= 4.1.16) 22 | activesupport (= 4.1.16) 23 | arel (~> 5.0.0) 24 | activesupport (4.1.16) 25 | i18n (~> 0.6, >= 0.6.9) 26 | json (~> 1.7, >= 1.7.7) 27 | minitest (~> 5.1) 28 | thread_safe (~> 0.1) 29 | tzinfo (~> 1.1) 30 | arel (5.0.1.20140414130214) 31 | benchmark-ips (2.7.2) 32 | benchmark-memory (0.1.2) 33 | memory_profiler (~> 0.9) 34 | builder (3.2.3) 35 | concurrent-ruby (1.0.5) 36 | erubis (2.7.0) 37 | i18n (0.8.1) 38 | json (1.8.6) 39 | mail (2.6.4) 40 | mime-types (>= 1.16, < 4) 41 | memory_profiler (0.9.8) 42 | mime-types (3.1) 43 | mime-types-data (~> 3.2015) 44 | mime-types-data (3.2016.0521) 45 | minitest (5.10.1) 46 | msgpack (1.1.0) 47 | oj (3.0.6) 48 | rack (1.5.5) 49 | rack-test (0.6.3) 50 | rack (>= 1.0) 51 | rails (4.1.16) 52 | actionmailer (= 4.1.16) 53 | actionpack (= 4.1.16) 54 | actionview (= 4.1.16) 55 | activemodel (= 4.1.16) 56 | activerecord (= 4.1.16) 57 | activesupport (= 4.1.16) 58 | bundler (>= 1.3.0, < 2.0) 59 | railties (= 4.1.16) 60 | sprockets-rails (~> 2.0) 61 | railties (4.1.16) 62 | actionpack (= 4.1.16) 63 | activesupport (= 4.1.16) 64 | rake (>= 0.8.7) 65 | thor (>= 0.18.1, < 2.0) 66 | rake (12.0.0) 67 | sprockets (3.7.1) 68 | concurrent-ruby (~> 1.0) 69 | rack (> 1, < 3) 70 | sprockets-rails (2.3.3) 71 | actionpack (>= 3.0) 72 | activesupport (>= 3.0) 73 | sprockets (>= 2.8, < 4.0) 74 | sqlite3 (1.3.13) 75 | terminal-table (1.7.3) 76 | unicode-display_width (~> 1.1.1) 77 | thor (0.19.4) 78 | thread_safe (0.3.6) 79 | tzinfo (1.2.2) 80 | thread_safe (~> 0.1) 81 | unicode-display_width (1.1.3) 82 | 83 | PLATFORMS 84 | ruby 85 | 86 | DEPENDENCIES 87 | benchmark-ips 88 | benchmark-memory 89 | msgpack 90 | oj (>= 3.0.6) 91 | rails (= 4.1.16) 92 | sqlite3 93 | terminal-table 94 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | actionmailer (4.1.16) 5 | actionpack (= 4.1.16) 6 | actionview (= 4.1.16) 7 | mail (~> 2.5, >= 2.5.4) 8 | actionpack (4.1.16) 9 | actionview (= 4.1.16) 10 | activesupport (= 4.1.16) 11 | rack (~> 1.5.2) 12 | rack-test (~> 0.6.2) 13 | actionview (4.1.16) 14 | activesupport (= 4.1.16) 15 | builder (~> 3.1) 16 | erubis (~> 2.7.0) 17 | activemodel (4.1.16) 18 | activesupport (= 4.1.16) 19 | builder (~> 3.1) 20 | activerecord (4.1.16) 21 | activemodel (= 4.1.16) 22 | activesupport (= 4.1.16) 23 | arel (~> 5.0.0) 24 | activesupport (4.1.16) 25 | i18n (~> 0.6, >= 0.6.9) 26 | json (~> 1.7, >= 1.7.7) 27 | minitest (~> 5.1) 28 | thread_safe (~> 0.1) 29 | tzinfo (~> 1.1) 30 | arel (5.0.1.20140414130214) 31 | benchmark-memory (0.1.2) 32 | memory_profiler (~> 0.9) 33 | builder (3.2.3) 34 | concurrent-ruby (1.0.5) 35 | erubis (2.7.0) 36 | i18n (0.8.1) 37 | json (1.8.6) 38 | mail (2.6.4) 39 | mime-types (>= 1.16, < 4) 40 | memory_profiler (0.9.8) 41 | mime-types (3.1) 42 | mime-types-data (~> 3.2015) 43 | mime-types-data (3.2016.0521) 44 | minitest (5.10.1) 45 | msgpack (1.1.0) 46 | oj (3.0.2) 47 | rack (1.5.5) 48 | rack-test (0.6.3) 49 | rack (>= 1.0) 50 | rails (4.1.16) 51 | actionmailer (= 4.1.16) 52 | actionpack (= 4.1.16) 53 | actionview (= 4.1.16) 54 | activemodel (= 4.1.16) 55 | activerecord (= 4.1.16) 56 | activesupport (= 4.1.16) 57 | bundler (>= 1.3.0, < 2.0) 58 | railties (= 4.1.16) 59 | sprockets-rails (~> 2.0) 60 | railties (4.1.16) 61 | actionpack (= 4.1.16) 62 | activesupport (= 4.1.16) 63 | rake (>= 0.8.7) 64 | thor (>= 0.18.1, < 2.0) 65 | rake (12.0.0) 66 | sprockets (3.7.1) 67 | concurrent-ruby (~> 1.0) 68 | rack (> 1, < 3) 69 | sprockets-rails (2.3.3) 70 | actionpack (>= 3.0) 71 | activesupport (>= 3.0) 72 | sprockets (>= 2.8, < 4.0) 73 | sqlite3 (1.3.13) 74 | terminal-table (1.7.3) 75 | unicode-display_width (~> 1.1.1) 76 | thor (0.19.4) 77 | thread_safe (0.3.6) 78 | tzinfo (1.2.3) 79 | thread_safe (~> 0.1) 80 | unicode-display_width (1.1.3) 81 | wwtd (1.3.0) 82 | 83 | PLATFORMS 84 | ruby 85 | 86 | DEPENDENCIES 87 | benchmark-memory 88 | msgpack 89 | oj (>= 3.0.2) 90 | rails (= 4.1.16) 91 | sqlite3 92 | terminal-table 93 | wwtd 94 | 95 | BUNDLED WITH 96 | 1.14.6 97 | -------------------------------------------------------------------------------- /gemfiles/4.2.8.gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | actionmailer (4.2.8) 5 | actionpack (= 4.2.8) 6 | actionview (= 4.2.8) 7 | activejob (= 4.2.8) 8 | mail (~> 2.5, >= 2.5.4) 9 | rails-dom-testing (~> 1.0, >= 1.0.5) 10 | actionpack (4.2.8) 11 | actionview (= 4.2.8) 12 | activesupport (= 4.2.8) 13 | rack (~> 1.6) 14 | rack-test (~> 0.6.2) 15 | rails-dom-testing (~> 1.0, >= 1.0.5) 16 | rails-html-sanitizer (~> 1.0, >= 1.0.2) 17 | actionview (4.2.8) 18 | activesupport (= 4.2.8) 19 | builder (~> 3.1) 20 | erubis (~> 2.7.0) 21 | rails-dom-testing (~> 1.0, >= 1.0.5) 22 | rails-html-sanitizer (~> 1.0, >= 1.0.3) 23 | activejob (4.2.8) 24 | activesupport (= 4.2.8) 25 | globalid (>= 0.3.0) 26 | activemodel (4.2.8) 27 | activesupport (= 4.2.8) 28 | builder (~> 3.1) 29 | activerecord (4.2.8) 30 | activemodel (= 4.2.8) 31 | activesupport (= 4.2.8) 32 | arel (~> 6.0) 33 | activesupport (4.2.8) 34 | i18n (~> 0.7) 35 | minitest (~> 5.1) 36 | thread_safe (~> 0.3, >= 0.3.4) 37 | tzinfo (~> 1.1) 38 | arel (6.0.4) 39 | benchmark-ips (2.7.2) 40 | benchmark-memory (0.1.2) 41 | memory_profiler (~> 0.9) 42 | builder (3.2.3) 43 | concurrent-ruby (1.0.5) 44 | erubis (2.7.0) 45 | globalid (0.3.7) 46 | activesupport (>= 4.1.0) 47 | i18n (0.8.1) 48 | loofah (2.0.3) 49 | nokogiri (>= 1.5.9) 50 | mail (2.6.4) 51 | mime-types (>= 1.16, < 4) 52 | memory_profiler (0.9.8) 53 | mime-types (3.1) 54 | mime-types-data (~> 3.2015) 55 | mime-types-data (3.2016.0521) 56 | mini_portile2 (2.1.0) 57 | minitest (5.10.1) 58 | msgpack (1.1.0) 59 | nokogiri (1.7.0.1) 60 | mini_portile2 (~> 2.1.0) 61 | oj (3.0.6) 62 | rack (1.6.5) 63 | rack-test (0.6.3) 64 | rack (>= 1.0) 65 | rails (4.2.8) 66 | actionmailer (= 4.2.8) 67 | actionpack (= 4.2.8) 68 | actionview (= 4.2.8) 69 | activejob (= 4.2.8) 70 | activemodel (= 4.2.8) 71 | activerecord (= 4.2.8) 72 | activesupport (= 4.2.8) 73 | bundler (>= 1.3.0, < 2.0) 74 | railties (= 4.2.8) 75 | sprockets-rails 76 | rails-deprecated_sanitizer (1.0.3) 77 | activesupport (>= 4.2.0.alpha) 78 | rails-dom-testing (1.0.8) 79 | activesupport (>= 4.2.0.beta, < 5.0) 80 | nokogiri (~> 1.6) 81 | rails-deprecated_sanitizer (>= 1.0.1) 82 | rails-html-sanitizer (1.0.3) 83 | loofah (~> 2.0) 84 | railties (4.2.8) 85 | actionpack (= 4.2.8) 86 | activesupport (= 4.2.8) 87 | rake (>= 0.8.7) 88 | thor (>= 0.18.1, < 2.0) 89 | rake (12.0.0) 90 | sprockets (3.7.1) 91 | concurrent-ruby (~> 1.0) 92 | rack (> 1, < 3) 93 | sprockets-rails (3.2.0) 94 | actionpack (>= 4.0) 95 | activesupport (>= 4.0) 96 | sprockets (>= 3.0.0) 97 | sqlite3 (1.3.13) 98 | terminal-table (1.7.3) 99 | unicode-display_width (~> 1.1.1) 100 | thor (0.19.4) 101 | thread_safe (0.3.6) 102 | tzinfo (1.2.2) 103 | thread_safe (~> 0.1) 104 | unicode-display_width (1.1.3) 105 | 106 | PLATFORMS 107 | ruby 108 | 109 | DEPENDENCIES 110 | benchmark-ips 111 | benchmark-memory 112 | msgpack 113 | oj (>= 3.0.6) 114 | rails (= 4.2.8) 115 | sqlite3 116 | terminal-table 117 | -------------------------------------------------------------------------------- /gemfiles/5.0.2.gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | actioncable (5.0.2) 5 | actionpack (= 5.0.2) 6 | nio4r (>= 1.2, < 3.0) 7 | websocket-driver (~> 0.6.1) 8 | actionmailer (5.0.2) 9 | actionpack (= 5.0.2) 10 | actionview (= 5.0.2) 11 | activejob (= 5.0.2) 12 | mail (~> 2.5, >= 2.5.4) 13 | rails-dom-testing (~> 2.0) 14 | actionpack (5.0.2) 15 | actionview (= 5.0.2) 16 | activesupport (= 5.0.2) 17 | rack (~> 2.0) 18 | rack-test (~> 0.6.3) 19 | rails-dom-testing (~> 2.0) 20 | rails-html-sanitizer (~> 1.0, >= 1.0.2) 21 | actionview (5.0.2) 22 | activesupport (= 5.0.2) 23 | builder (~> 3.1) 24 | erubis (~> 2.7.0) 25 | rails-dom-testing (~> 2.0) 26 | rails-html-sanitizer (~> 1.0, >= 1.0.3) 27 | activejob (5.0.2) 28 | activesupport (= 5.0.2) 29 | globalid (>= 0.3.6) 30 | activemodel (5.0.2) 31 | activesupport (= 5.0.2) 32 | activerecord (5.0.2) 33 | activemodel (= 5.0.2) 34 | activesupport (= 5.0.2) 35 | arel (~> 7.0) 36 | activesupport (5.0.2) 37 | concurrent-ruby (~> 1.0, >= 1.0.2) 38 | i18n (~> 0.7) 39 | minitest (~> 5.1) 40 | tzinfo (~> 1.1) 41 | arel (7.1.4) 42 | benchmark-ips (2.7.2) 43 | benchmark-memory (0.1.2) 44 | memory_profiler (~> 0.9) 45 | builder (3.2.3) 46 | concurrent-ruby (1.0.5) 47 | erubis (2.7.0) 48 | globalid (0.3.7) 49 | activesupport (>= 4.1.0) 50 | i18n (0.8.1) 51 | loofah (2.0.3) 52 | nokogiri (>= 1.5.9) 53 | mail (2.6.4) 54 | mime-types (>= 1.16, < 4) 55 | memory_profiler (0.9.8) 56 | method_source (0.8.2) 57 | mime-types (3.1) 58 | mime-types-data (~> 3.2015) 59 | mime-types-data (3.2016.0521) 60 | mini_portile2 (2.1.0) 61 | minitest (5.10.1) 62 | msgpack (1.1.0) 63 | nio4r (2.0.0) 64 | nokogiri (1.7.0.1) 65 | mini_portile2 (~> 2.1.0) 66 | oj (3.0.6) 67 | rack (2.0.1) 68 | rack-test (0.6.3) 69 | rack (>= 1.0) 70 | rails (5.0.2) 71 | actioncable (= 5.0.2) 72 | actionmailer (= 5.0.2) 73 | actionpack (= 5.0.2) 74 | actionview (= 5.0.2) 75 | activejob (= 5.0.2) 76 | activemodel (= 5.0.2) 77 | activerecord (= 5.0.2) 78 | activesupport (= 5.0.2) 79 | bundler (>= 1.3.0, < 2.0) 80 | railties (= 5.0.2) 81 | sprockets-rails (>= 2.0.0) 82 | rails-dom-testing (2.0.2) 83 | activesupport (>= 4.2.0, < 6.0) 84 | nokogiri (~> 1.6) 85 | rails-html-sanitizer (1.0.3) 86 | loofah (~> 2.0) 87 | railties (5.0.2) 88 | actionpack (= 5.0.2) 89 | activesupport (= 5.0.2) 90 | method_source 91 | rake (>= 0.8.7) 92 | thor (>= 0.18.1, < 2.0) 93 | rake (12.0.0) 94 | sprockets (3.7.1) 95 | concurrent-ruby (~> 1.0) 96 | rack (> 1, < 3) 97 | sprockets-rails (3.2.0) 98 | actionpack (>= 4.0) 99 | activesupport (>= 4.0) 100 | sprockets (>= 3.0.0) 101 | sqlite3 (1.3.13) 102 | terminal-table (1.7.3) 103 | unicode-display_width (~> 1.1.1) 104 | thor (0.19.4) 105 | thread_safe (0.3.6) 106 | tzinfo (1.2.2) 107 | thread_safe (~> 0.1) 108 | unicode-display_width (1.1.3) 109 | websocket-driver (0.6.5) 110 | websocket-extensions (>= 0.1.0) 111 | websocket-extensions (0.1.2) 112 | 113 | PLATFORMS 114 | ruby 115 | 116 | DEPENDENCIES 117 | benchmark-ips 118 | benchmark-memory 119 | msgpack 120 | oj (>= 3.0.6) 121 | rails (= 5.0.2) 122 | sqlite3 123 | terminal-table 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Benchmark JSON implementations in Ruby 2 | 3 | ## Why 4 | 5 | `to_json` in Rails project is not the same as `JSON.generate` or `to_json` in non-Rails project. See benchmarks [Rails to_json + Oj.mimic_JSON](https://github.com/stereobooster/ruby-json-benchmark#rails-to_json--ojmimic_json) vs [No Rails to_json + Oj.mimic_JSON](https://github.com/stereobooster/ruby-json-benchmark#no-rails-to_json--ojmimic_json) (below). 6 | 7 | ## Compatibility test 8 | 9 | Comparing Rails `to_json` with other JSON implementations: 10 | 11 | ``` 12 | bundle exec ruby compatibility_test.rb 13 | Comparing Rails to_json with other JSON implementations 14 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 15 | | class | JSON to_json | Oj.dump | Oj::Rails.encode | Oj to_json | msgpack "rails" | 16 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 17 | | Regexp | 👌 | 👌 | 👌 | 👌 | 👌 | 18 | | FalseClass | 👌 | 👌 | 👌 | 👌 | 👌 | 19 | | NilClass | 👌 | 👌 | 👌 | 👌 | 👌 | 20 | | Object | ❌ | 👌 | 👌 | 👌 | 👌 | 21 | | TrueClass | 👌 | 👌 | 👌 | 👌 | 👌 | 22 | | String | 👌 | 👌 | 👌 | 👌 | 👌 | 23 | | StringChinese | 👌 | 👌 | 👌 | 👌 | 👌 | 24 | | StringSpecial | ❌ | 👌 | 👌 | 👌 | 👌 | 25 | | StringSpecial2 | 👌 | 👌 | 👌 | 👌 | 👌 | 26 | | StringSpecial3 | 👌 | 👌 | 👌 | 👌 | 👌 | 27 | | Numeric | 👌 | 👌 | 👌 | 👌 | 👌 | 28 | | Symbol | 👌 | 👌 | 👌 | 👌 | 👌 | 29 | | Time | ❌ | 👌 | 👌 | 👌 | 👌 | 30 | | Array | 👌 | 👌 | 👌 | 👌 | 👌 | 31 | | Hash | 👌 | 👌 | 👌 | 👌 | 👌 | 32 | | HashNotEmpty | 👌 | 👌 | 👌 | 👌 | 👌 | 33 | | Date | 👌 | 👌 | 👌 | 👌 | 👌 | 34 | | DateTime | ❌ | 👌 | 👌 | 👌 | 👌 | 35 | | Enumerable | ❌ | 👌 | 👌 | 👌 | 👌 | 36 | | BigDecimal | ❌ | 👌 | 👌 | 👌 | 👌 | 37 | | BigDecimalInfinity | ❌ | 👌 | 👌 | 👌 | 👌 | 38 | | Struct | ❌ | 👌 | 👌 | 👌 | 👌 | 39 | | Float | 👌 | 👌 | 👌 | 👌 | 👌 | 40 | | FloatInfinity | 💀 | 👌 | 👌 | 👌 | ❌ | 41 | | Range | 👌 | 👌 | 👌 | 👌 | 👌 | 42 | | Complex | 👌 | 👌 | 👌 | 👌 | 👌 | 43 | | Exception | ❌ | 👌 | 👌 | 👌 | 👌 | 44 | | OpenStruct | ❌ | 👌 | 👌 | 👌 | 👌 | 45 | | Rational | 👌 | 👌 | 👌 | 👌 | 👌 | 46 | | Process::Status | ❌ | 👌 | 👌 | 👌 | 👌 | 47 | | ActiveSupport::TimeWithZone | ❌ | 👌 | 👌 | 👌 | 👌 | 48 | | ActiveModel::Errors | ❌ | 👌 | 👌 | 👌 | 👌 | 49 | | ActiveSupport::Duration | ❌ | 👌 | 👌 | 👌 | 👌 | 50 | | ActiveSupport::Multibyte::Chars | ❌ | 👌 | 👌 | 👌 | 👌 | 51 | | ActiveRecord::Relation | ❌ | 👌 | 👌 | 👌 | 👌 | 52 | | ActiveRecord | ❌ | 👌 | 👌 | 👌 | 👌 | 53 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 54 | ``` 55 | 56 | **Note**: msgpack is not JSON, so comparing results of serialization + deserialization e.g. 57 | 58 | ```ruby 59 | ActiveSupport::JSON.decode(obj.to_json) vs MessagePack.unpack(obj.to_msgpack) 60 | ``` 61 | 62 | See comparison across Ruby/Rails version in [test_report.txt](test_report.txt). Report was generated with command: `wwtd &> test_report.txt`. 63 | 64 | Tests based on [as_json](http://apidock.com/rails/ActiveResource/Base/as_json) implementations. 65 | 66 | See also: 67 | - [json gem](https://github.com/ruby/ruby/tree/202bbda2bf5f25343e286099140fb9282880ecba/ext/json/lib/json/add). 68 | - [active_support/json/encoding.rb](https://github.com/rails/rails/blob/92703a9ea5d8b96f30e0b706b801c9185ef14f0e/activesupport/lib/active_support/json/encoding.rb) 69 | - [lave](https://github.com/jed/lave) 70 | - [Data formats](http://awesomeawesome.party/awesome-microservices#data-formats) 71 | 72 | ## Benchmark Rails to_json vs Oj.dump 73 | 74 | ``` 75 | Calculating ------------------------------------- 76 | to_json: 340.131M memsize ( 168.000 retained) 77 | 6.660M objects ( 2.000 retained) 78 | 50.000 strings ( 0.000 retained) 79 | Oj.dump o 55.880M memsize ( 0.000 retained) 80 | 990.000k objects ( 0.000 retained) 81 | 38.000 strings ( 0.000 retained) 82 | Oj.dump c 55.880M memsize ( 0.000 retained) 83 | 990.000k objects ( 0.000 retained) 84 | 38.000 strings ( 0.000 retained) 85 | Oj.dump c, aj 55.880M memsize ( 0.000 retained) 86 | 990.000k objects ( 0.000 retained) 87 | 38.000 strings ( 0.000 retained) 88 | 89 | Comparison: 90 | Oj.dump c, aj: 55880000 allocated 91 | Oj.dump o: 55880000 allocated - same 92 | Oj.dump c: 55880000 allocated - same 93 | to_json:: 340130720 allocated - 6.09x more 94 | --------------------------------------------- 95 | 96 | user system total real 97 | to_json: 2.810000 0.170000 2.980000 ( 3.048407) 98 | Oj.dump o 0.630000 0.020000 0.650000 ( 0.666360) 99 | Oj.dump c 0.440000 0.010000 0.450000 ( 0.459752) 100 | Oj.dump c, aj 0.530000 0.020000 0.550000 ( 0.554771) 101 | ``` 102 | 103 | ## Rails to_json + Oj.mimic_JSON 104 | 105 | ``` 106 | bundle exec ruby benchmark1.rb 107 | Calculating ------------------------------------- 108 | to_json: 18.730M memsize ( 0.000 retained) 109 | 270.000k objects ( 0.000 retained) 110 | 3.000 strings ( 0.000 retained) 111 | JSON: 2.970M memsize ( 0.000 retained) 112 | 20.000k objects ( 0.000 retained) 113 | 1.000 strings ( 0.000 retained) 114 | Oj: 2.970M memsize ( 0.000 retained) 115 | 20.000k objects ( 0.000 retained) 116 | 1.000 strings ( 0.000 retained) 117 | 118 | Comparison: 119 | Oj:: 2970000 allocated 120 | JSON:: 2970000 allocated - same 121 | to_json:: 18730000 allocated - 6.31x more <---- PAY ATTENTION 122 | 123 | --------------------------------------------- 124 | 125 | user system total real 126 | to_json: 0.080000 0.000000 0.080000 ( 0.079702) 127 | JSON: 0.010000 0.000000 0.010000 ( 0.012702) 128 | Oj: 0.020000 0.000000 0.020000 ( 0.015271) 129 | ``` 130 | 131 | ## No Rails to_json + Oj.mimic_JSON 132 | 133 | ``` 134 | bundle exec ruby benchmark1.rb 135 | Calculating ------------------------------------- 136 | to_json: 2.970M memsize ( 0.000 retained) 137 | 20.000k objects ( 0.000 retained) 138 | 1.000 strings ( 0.000 retained) 139 | JSON: 2.970M memsize ( 0.000 retained) 140 | 20.000k objects ( 0.000 retained) 141 | 1.000 strings ( 0.000 retained) 142 | Oj: 2.970M memsize ( 0.000 retained) 143 | 20.000k objects ( 0.000 retained) 144 | 1.000 strings ( 0.000 retained) 145 | 146 | Comparison: 147 | to_json:: 2970000 allocated 148 | JSON:: 2970000 allocated - same 149 | Oj:: 2970000 allocated - same 150 | 151 | --------------------------------------------- 152 | 153 | user system total real 154 | to_json: 0.020000 0.000000 0.020000 ( 0.014124) 155 | JSON: 0.020000 0.010000 0.030000 ( 0.024667) 156 | Oj: 0.020000 0.000000 0.020000 ( 0.028081) 157 | ``` 158 | -------------------------------------------------------------------------------- /test_report.txt: -------------------------------------------------------------------------------- 1 | Ignoring: branches, cache, langauge, sudo 2 | START gemfile: gemfiles/4.1.16.gemfile rvm: 2.2.6 3 | bundle install --deployment --path /ruby-json-benchmark/vendor/bundle --quiet 4 | bundle exec ruby compatibility_test.rb && bundle exec ruby benchmark.rb 5 | 6 | Comparing Rails to_json with other JSON implementations 7 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 8 | | class | JSON to_json | Oj.dump | Oj::Rails.encode | Oj to_json | msgpack "rails" | 9 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 10 | | Regexp | 👌 | 👌 | 👌 | 👌 | 👌 | 11 | | FalseClass | 👌 | 👌 | 👌 | 👌 | 👌 | 12 | | NilClass | 👌 | 👌 | 👌 | 👌 | 👌 | 13 | | Object | ❌ | 👌 | 👌 | 👌 | 👌 | 14 | | TrueClass | 👌 | 👌 | 👌 | 👌 | 👌 | 15 | | String | 👌 | 👌 | 👌 | 👌 | 👌 | 16 | | StringChinese | 👌 | 👌 | 👌 | 👌 | 👌 | 17 | | StringSpecial | ❌ | 👌 | 👌 | 👌 | 👌 | 18 | | StringSpecial2 | 👌 | 👌 | 👌 | 👌 | 👌 | 19 | | StringSpecial3 | 👌 | 👌 | 👌 | 👌 | 👌 | 20 | | Numeric | 👌 | 👌 | 👌 | 👌 | 👌 | 21 | | Symbol | 👌 | 👌 | 👌 | 👌 | 👌 | 22 | | Time | ❌ | 👌 | 👌 | 👌 | 👌 | 23 | | Array | 👌 | 👌 | 👌 | 👌 | 👌 | 24 | | Hash | 👌 | 👌 | 👌 | 👌 | 👌 | 25 | | HashNotEmpty | 👌 | 👌 | 👌 | 👌 | 👌 | 26 | | Date | 👌 | 👌 | 👌 | 👌 | 👌 | 27 | | DateTime | ❌ | 👌 | 👌 | 👌 | 👌 | 28 | | Enumerable | ❌ | 👌 | 👌 | 👌 | 👌 | 29 | | BigDecimal | ❌ | 👌 | 👌 | 👌 | 👌 | 30 | | BigDecimalInfinity | ❌ | 👌 | 👌 | 👌 | 👌 | 31 | | Struct | ❌ | 👌 | 👌 | 👌 | 👌 | 32 | | Float | 👌 | 👌 | 👌 | 👌 | 👌 | 33 | | FloatInfinity | 💀 | 👌 | 👌 | 👌 | ❌ | 34 | | Range | 👌 | 👌 | 👌 | 👌 | 👌 | 35 | | Complex | 👌 | 👌 | 👌 | 👌 | 👌 | 36 | | Exception | ❌ | 👌 | 👌 | 👌 | 👌 | 37 | | OpenStruct | ❌ | 👌 | 👌 | 👌 | 👌 | 38 | | Rational | 👌 | 👌 | 👌 | 👌 | 👌 | 39 | | Process::Status | ❌ | 👌 | 👌 | 👌 | 👌 | 40 | | AsJson | ❌ | 👌 | 👌 | 👌 | 👌 | 41 | | ToJson | 👌 | ❌ | ❌ | 👌 | ❌ | 42 | | ActiveSupport::TimeWithZone | ❌ | 👌 | 👌 | 👌 | 👌 | 43 | | ActiveModel::Errors | ❌ | 👌 | 👌 | 👌 | 👌 | 44 | | ActiveSupport::Duration | ❌ | 👌 | 👌 | 👌 | 👌 | 45 | | ActiveSupport::Multibyte::Chars | ❌ | 👌 | 👌 | 👌 | 👌 | 46 | | ActiveRecord::Relation | ❌ | 👌 | 👌 | 👌 | 👌 | 47 | | ActiveRecord | ❌ | 💀 | 👌 | 👌 | 👌 | 48 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 49 | 50 | Calculating ------------------------------------- 51 | Rails to_json 562.153M memsize ( 248.000 retained) 52 | 11.400M objects ( 4.000 retained) 53 | 50.000 strings ( 0.000 retained) 54 | msgpack 274.930M memsize ( 232.000 retained) 55 | 4.780M objects ( 1.000 retained) 56 | 50.000 strings ( 0.000 retained) 57 | Oj.dump 368.910M memsize ( 0.000 retained) 58 | 5.750M objects ( 0.000 retained) 59 | 50.000 strings ( 0.000 retained) 60 | Oj::Rails.encode 85.520M memsize ( 0.000 retained) 61 | 1.490M objects ( 0.000 retained) 62 | 25.000 strings ( 0.000 retained) 63 | 64 | Comparison: 65 | Oj::Rails.encode: 85520000 allocated 66 | msgpack: 274930232 allocated - 3.21x more 67 | Oj.dump: 368910000 allocated - 4.31x more 68 | Rails to_json: 562152520 allocated - 6.57x more 69 | --------------------------------------------- 70 | 71 | Warming up -------------------------------------- 72 | Rails to_json 259.000 i/100ms 73 | msgpack 550.000 i/100ms 74 | Oj.dump 513.000 i/100ms 75 | Oj::Rails.encode 1.745k i/100ms 76 | Calculating ------------------------------------- 77 | Rails to_json 2.755k (± 3.9%) i/s - 13.986k in 5.084270s 78 | msgpack 6.582k (± 6.2%) i/s - 33.000k in 5.034478s 79 | Oj.dump 5.895k (± 3.4%) i/s - 29.754k in 5.053206s 80 | Oj::Rails.encode 17.749k (± 4.6%) i/s - 88.995k in 5.025052s 81 | 82 | Comparison: 83 | Oj::Rails.encode: 17749.0 i/s 84 | msgpack: 6582.1 i/s - 2.70x slower 85 | Oj.dump: 5895.4 i/s - 3.01x slower 86 | Rails to_json: 2755.3 i/s - 6.44x slower 87 | 88 | 89 | SUCCESS gemfile: gemfiles/4.1.16.gemfile rvm: 2.2.6 90 | START gemfile: gemfiles/4.1.16.gemfile rvm: 2.3.3 91 | bundle install --deployment --path /ruby-json-benchmark/vendor/bundle --quiet 92 | bundle exec ruby compatibility_test.rb && bundle exec ruby benchmark.rb 93 | 94 | Comparing Rails to_json with other JSON implementations 95 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 96 | | class | JSON to_json | Oj.dump | Oj::Rails.encode | Oj to_json | msgpack "rails" | 97 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 98 | | Regexp | 👌 | 👌 | 👌 | 👌 | 👌 | 99 | | FalseClass | 👌 | 👌 | 👌 | 👌 | 👌 | 100 | | NilClass | 👌 | 👌 | 👌 | 👌 | 👌 | 101 | | Object | ❌ | 👌 | 👌 | 👌 | 👌 | 102 | | TrueClass | 👌 | 👌 | 👌 | 👌 | 👌 | 103 | | String | 👌 | 👌 | 👌 | 👌 | 👌 | 104 | | StringChinese | 👌 | 👌 | 👌 | 👌 | 👌 | 105 | | StringSpecial | ❌ | 👌 | 👌 | 👌 | 👌 | 106 | | StringSpecial2 | 👌 | 👌 | 👌 | 👌 | 👌 | 107 | | StringSpecial3 | 👌 | 👌 | 👌 | 👌 | 👌 | 108 | | Numeric | 👌 | 👌 | 👌 | 👌 | 👌 | 109 | | Symbol | 👌 | 👌 | 👌 | 👌 | 👌 | 110 | | Time | ❌ | 👌 | 👌 | 👌 | 👌 | 111 | | Array | 👌 | 👌 | 👌 | 👌 | 👌 | 112 | | Hash | 👌 | 👌 | 👌 | 👌 | 👌 | 113 | | HashNotEmpty | 👌 | 👌 | 👌 | 👌 | 👌 | 114 | | Date | 👌 | 👌 | 👌 | 👌 | 👌 | 115 | | DateTime | ❌ | 👌 | 👌 | 👌 | 👌 | 116 | | Enumerable | ❌ | 👌 | 👌 | 👌 | 👌 | 117 | | BigDecimal | ❌ | 👌 | 👌 | 👌 | 👌 | 118 | | BigDecimalInfinity | ❌ | 👌 | 👌 | 👌 | 👌 | 119 | | Struct | ❌ | 👌 | 👌 | 👌 | 👌 | 120 | | Float | 👌 | 👌 | 👌 | 👌 | 👌 | 121 | | FloatInfinity | 💀 | 👌 | 👌 | 👌 | ❌ | 122 | | Range | 👌 | 👌 | 👌 | 👌 | 👌 | 123 | | Complex | 👌 | 👌 | 👌 | 👌 | 👌 | 124 | | Exception | ❌ | 👌 | 👌 | 👌 | 👌 | 125 | | OpenStruct | ❌ | 👌 | 👌 | 👌 | 👌 | 126 | | Rational | 👌 | 👌 | 👌 | 👌 | 👌 | 127 | | Process::Status | ❌ | 👌 | 👌 | 👌 | 👌 | 128 | | AsJson | ❌ | 👌 | 👌 | 👌 | 👌 | 129 | | ToJson | 👌 | ❌ | ❌ | 👌 | ❌ | 130 | | ActiveSupport::TimeWithZone | ❌ | 👌 | 👌 | 👌 | 👌 | 131 | | ActiveModel::Errors | ❌ | 👌 | 👌 | 👌 | 👌 | 132 | | ActiveSupport::Duration | ❌ | 👌 | 👌 | 👌 | 👌 | 133 | | ActiveSupport::Multibyte::Chars | ❌ | 👌 | 👌 | 👌 | 👌 | 134 | | ActiveRecord::Relation | ❌ | 👌 | 👌 | 👌 | 👌 | 135 | | ActiveRecord | ❌ | 💀 | 👌 | 👌 | 👌 | 136 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 137 | 138 | Calculating ------------------------------------- 139 | Rails to_json 558.953M memsize ( 248.000 retained) 140 | 11.320M objects ( 4.000 retained) 141 | 50.000 strings ( 0.000 retained) 142 | msgpack 269.341M memsize ( 10.952k retained) 143 | 4.640M objects ( 21.000 retained) 144 | 50.000 strings ( 0.000 retained) 145 | Oj.dump 363.710M memsize ( 0.000 retained) 146 | 5.620M objects ( 0.000 retained) 147 | 50.000 strings ( 0.000 retained) 148 | Oj::Rails.encode 86.720M memsize ( 0.000 retained) 149 | 1.520M objects ( 0.000 retained) 150 | 27.000 strings ( 0.000 retained) 151 | 152 | Comparison: 153 | Oj::Rails.encode: 86720000 allocated 154 | msgpack: 269340952 allocated - 3.11x more 155 | Oj.dump: 363710000 allocated - 4.19x more 156 | Rails to_json: 558952520 allocated - 6.45x more 157 | --------------------------------------------- 158 | 159 | Warming up -------------------------------------- 160 | Rails to_json 276.000 i/100ms 161 | msgpack 660.000 i/100ms 162 | Oj.dump 456.000 i/100ms 163 | Oj::Rails.encode 1.644k i/100ms 164 | Calculating ------------------------------------- 165 | Rails to_json 2.646k (± 5.3%) i/s - 13.248k in 5.020660s 166 | msgpack 6.562k (± 8.2%) i/s - 33.000k in 5.059452s 167 | Oj.dump 5.642k (± 9.6%) i/s - 28.272k in 5.055156s 168 | Oj::Rails.encode 17.242k (± 6.2%) i/s - 87.132k in 5.073235s 169 | 170 | Comparison: 171 | Oj::Rails.encode: 17241.8 i/s 172 | msgpack: 6562.5 i/s - 2.63x slower 173 | Oj.dump: 5641.6 i/s - 3.06x slower 174 | Rails to_json: 2646.0 i/s - 6.52x slower 175 | 176 | 177 | SUCCESS gemfile: gemfiles/4.1.16.gemfile rvm: 2.3.3 178 | START gemfile: gemfiles/4.1.16.gemfile rvm: 2.4.0 179 | bundle install --deployment --path /ruby-json-benchmark/vendor/bundle --quiet 180 | bundle exec ruby compatibility_test.rb && bundle exec ruby benchmark.rb 181 | /ruby-json-benchmark/vendor/bundle/ruby/2.4.0/gems/activesupport-4.1.16/lib/active_support/core_ext/numeric/time.rb:50:in `*': ActiveSupport::Duration can't be coerced into Integer (TypeError) 182 | from /ruby-json-benchmark/vendor/bundle/ruby/2.4.0/gems/activesupport-4.1.16/lib/active_support/core_ext/numeric/time.rb:50:in `days' 183 | from /ruby-json-benchmark/vendor/bundle/ruby/2.4.0/gems/activesupport-4.1.16/lib/active_support/core_ext/integer/time.rb:36:in `months' 184 | from /ruby-json-benchmark/lib/test_data_rails.rb:30:in `' 185 | from compatibility_test.rb:10:in `require' 186 | from compatibility_test.rb:10:in `
' 187 | FAILURE gemfile: gemfiles/4.1.16.gemfile rvm: 2.4.0 188 | START gemfile: gemfiles/4.2.8.gemfile rvm: 2.2.6 189 | bundle install --deployment --path /ruby-json-benchmark/vendor/bundle --quiet 190 | bundle exec ruby compatibility_test.rb && bundle exec ruby benchmark.rb 191 | 192 | Comparing Rails to_json with other JSON implementations 193 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 194 | | class | JSON to_json | Oj.dump | Oj::Rails.encode | Oj to_json | msgpack "rails" | 195 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 196 | | Regexp | 👌 | 👌 | 👌 | 👌 | 👌 | 197 | | FalseClass | 👌 | 👌 | 👌 | 👌 | 👌 | 198 | | NilClass | 👌 | 👌 | 👌 | 👌 | 👌 | 199 | | Object | ❌ | 👌 | 👌 | 👌 | 👌 | 200 | | TrueClass | 👌 | 👌 | 👌 | 👌 | 👌 | 201 | | String | 👌 | 👌 | 👌 | 👌 | 👌 | 202 | | StringChinese | 👌 | 👌 | 👌 | 👌 | 👌 | 203 | | StringSpecial | ❌ | 👌 | 👌 | 👌 | 👌 | 204 | | StringSpecial2 | 👌 | 👌 | 👌 | 👌 | 👌 | 205 | | StringSpecial3 | 👌 | 👌 | 👌 | 👌 | 👌 | 206 | | Numeric | 👌 | 👌 | 👌 | 👌 | 👌 | 207 | | Symbol | 👌 | 👌 | 👌 | 👌 | 👌 | 208 | | Time | ❌ | 👌 | 👌 | 👌 | 👌 | 209 | | Array | 👌 | 👌 | 👌 | 👌 | 👌 | 210 | | Hash | 👌 | 👌 | 👌 | 👌 | 👌 | 211 | | HashNotEmpty | 👌 | 👌 | 👌 | 👌 | 👌 | 212 | | Date | 👌 | 👌 | 👌 | 👌 | 👌 | 213 | | DateTime | ❌ | 👌 | 👌 | 👌 | 👌 | 214 | | Enumerable | ❌ | 👌 | 👌 | 👌 | 👌 | 215 | | BigDecimal | ❌ | 👌 | 👌 | 👌 | 👌 | 216 | | BigDecimalInfinity | ❌ | 👌 | 👌 | 👌 | 👌 | 217 | | Struct | ❌ | 👌 | 👌 | 👌 | 👌 | 218 | | Float | 👌 | 👌 | 👌 | 👌 | 👌 | 219 | | FloatInfinity | 💀 | 👌 | 👌 | 👌 | ❌ | 220 | | Range | 👌 | 👌 | 👌 | 👌 | 👌 | 221 | | Complex | 👌 | 👌 | 👌 | 👌 | 👌 | 222 | | Exception | ❌ | 👌 | 👌 | 👌 | 👌 | 223 | | OpenStruct | ❌ | 👌 | 👌 | 👌 | 👌 | 224 | | Rational | 👌 | 👌 | 👌 | 👌 | 👌 | 225 | | Process::Status | ❌ | 👌 | 👌 | 👌 | 👌 | 226 | | AsJson | ❌ | 👌 | 👌 | 👌 | 👌 | 227 | | ToJson | 👌 | ❌ | ❌ | 👌 | ❌ | 228 | | ActiveSupport::TimeWithZone | ❌ | 👌 | 👌 | 👌 | 👌 | 229 | | ActiveModel::Errors | ❌ | 👌 | 👌 | 👌 | 👌 | 230 | | ActiveSupport::Duration | ❌ | 👌 | 👌 | 👌 | 👌 | 231 | | ActiveSupport::Multibyte::Chars | ❌ | 👌 | 👌 | 👌 | 👌 | 232 | | ActiveRecord::Relation | ❌ | 👌 | 👌 | 👌 | 👌 | 233 | | ActiveRecord | ❌ | 💀 | 👌 | 👌 | 👌 | 234 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 235 | 236 | Calculating ------------------------------------- 237 | Rails to_json 562.153M memsize ( 344.000 retained) 238 | 11.400M objects ( 5.000 retained) 239 | 50.000 strings ( 0.000 retained) 240 | msgpack 274.930M memsize ( 232.000 retained) 241 | 4.780M objects ( 1.000 retained) 242 | 50.000 strings ( 0.000 retained) 243 | Oj.dump 368.910M memsize ( 0.000 retained) 244 | 5.750M objects ( 0.000 retained) 245 | 50.000 strings ( 0.000 retained) 246 | Oj::Rails.encode 85.520M memsize ( 0.000 retained) 247 | 1.490M objects ( 0.000 retained) 248 | 25.000 strings ( 0.000 retained) 249 | 250 | Comparison: 251 | Oj::Rails.encode: 85520000 allocated 252 | msgpack: 274930232 allocated - 3.21x more 253 | Oj.dump: 368910000 allocated - 4.31x more 254 | Rails to_json: 562152520 allocated - 6.57x more 255 | --------------------------------------------- 256 | 257 | Warming up -------------------------------------- 258 | Rails to_json 252.000 i/100ms 259 | msgpack 625.000 i/100ms 260 | Oj.dump 568.000 i/100ms 261 | Oj::Rails.encode 1.781k i/100ms 262 | Calculating ------------------------------------- 263 | Rails to_json 2.716k (± 5.3%) i/s - 13.608k in 5.024179s 264 | msgpack 6.769k (± 4.4%) i/s - 34.375k in 5.088727s 265 | Oj.dump 6.000k (± 4.8%) i/s - 30.104k in 5.029655s 266 | Oj::Rails.encode 18.143k (± 4.1%) i/s - 90.831k in 5.014967s 267 | 268 | Comparison: 269 | Oj::Rails.encode: 18143.1 i/s 270 | msgpack: 6768.8 i/s - 2.68x slower 271 | Oj.dump: 5999.9 i/s - 3.02x slower 272 | Rails to_json: 2716.0 i/s - 6.68x slower 273 | 274 | 275 | SUCCESS gemfile: gemfiles/4.2.8.gemfile rvm: 2.2.6 276 | START gemfile: gemfiles/4.2.8.gemfile rvm: 2.3.3 277 | bundle install --deployment --path /ruby-json-benchmark/vendor/bundle --quiet 278 | bundle exec ruby compatibility_test.rb && bundle exec ruby benchmark.rb 279 | 280 | Comparing Rails to_json with other JSON implementations 281 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 282 | | class | JSON to_json | Oj.dump | Oj::Rails.encode | Oj to_json | msgpack "rails" | 283 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 284 | | Regexp | 👌 | 👌 | 👌 | 👌 | 👌 | 285 | | FalseClass | 👌 | 👌 | 👌 | 👌 | 👌 | 286 | | NilClass | 👌 | 👌 | 👌 | 👌 | 👌 | 287 | | Object | ❌ | 👌 | 👌 | 👌 | 👌 | 288 | | TrueClass | 👌 | 👌 | 👌 | 👌 | 👌 | 289 | | String | 👌 | 👌 | 👌 | 👌 | 👌 | 290 | | StringChinese | 👌 | 👌 | 👌 | 👌 | 👌 | 291 | | StringSpecial | ❌ | 👌 | 👌 | 👌 | 👌 | 292 | | StringSpecial2 | 👌 | 👌 | 👌 | 👌 | 👌 | 293 | | StringSpecial3 | 👌 | 👌 | 👌 | 👌 | 👌 | 294 | | Numeric | 👌 | 👌 | 👌 | 👌 | 👌 | 295 | | Symbol | 👌 | 👌 | 👌 | 👌 | 👌 | 296 | | Time | ❌ | 👌 | 👌 | 👌 | 👌 | 297 | | Array | 👌 | 👌 | 👌 | 👌 | 👌 | 298 | | Hash | 👌 | 👌 | 👌 | 👌 | 👌 | 299 | | HashNotEmpty | 👌 | 👌 | 👌 | 👌 | 👌 | 300 | | Date | 👌 | 👌 | 👌 | 👌 | 👌 | 301 | | DateTime | ❌ | 👌 | 👌 | 👌 | 👌 | 302 | | Enumerable | ❌ | 👌 | 👌 | 👌 | 👌 | 303 | | BigDecimal | ❌ | 👌 | 👌 | 👌 | 👌 | 304 | | BigDecimalInfinity | ❌ | 👌 | 👌 | 👌 | 👌 | 305 | | Struct | ❌ | 👌 | 👌 | 👌 | 👌 | 306 | | Float | 👌 | 👌 | 👌 | 👌 | 👌 | 307 | | FloatInfinity | 💀 | 👌 | 👌 | 👌 | ❌ | 308 | | Range | 👌 | 👌 | 👌 | 👌 | 👌 | 309 | | Complex | 👌 | 👌 | 👌 | 👌 | 👌 | 310 | | Exception | ❌ | 👌 | 👌 | 👌 | 👌 | 311 | | OpenStruct | ❌ | 👌 | 👌 | 👌 | 👌 | 312 | | Rational | 👌 | 👌 | 👌 | 👌 | 👌 | 313 | | Process::Status | ❌ | 👌 | 👌 | 👌 | 👌 | 314 | | AsJson | ❌ | 👌 | 👌 | 👌 | 👌 | 315 | | ToJson | 👌 | ❌ | ❌ | 👌 | ❌ | 316 | | ActiveSupport::TimeWithZone | ❌ | 👌 | 👌 | 👌 | 👌 | 317 | | ActiveModel::Errors | ❌ | 👌 | 👌 | 👌 | 👌 | 318 | | ActiveSupport::Duration | ❌ | 👌 | 👌 | 👌 | 👌 | 319 | | ActiveSupport::Multibyte::Chars | ❌ | 👌 | 👌 | 👌 | 👌 | 320 | | ActiveRecord::Relation | ❌ | 👌 | 👌 | 👌 | 👌 | 321 | | ActiveRecord | ❌ | 💀 | 👌 | 👌 | 👌 | 322 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 323 | 324 | Calculating ------------------------------------- 325 | Rails to_json 558.953M memsize ( 344.000 retained) 326 | 11.320M objects ( 5.000 retained) 327 | 50.000 strings ( 0.000 retained) 328 | msgpack 269.341M memsize ( 10.952k retained) 329 | 4.640M objects ( 21.000 retained) 330 | 50.000 strings ( 0.000 retained) 331 | Oj.dump 363.710M memsize ( 0.000 retained) 332 | 5.620M objects ( 0.000 retained) 333 | 50.000 strings ( 0.000 retained) 334 | Oj::Rails.encode 86.720M memsize ( 0.000 retained) 335 | 1.520M objects ( 0.000 retained) 336 | 27.000 strings ( 0.000 retained) 337 | 338 | Comparison: 339 | Oj::Rails.encode: 86720000 allocated 340 | msgpack: 269340952 allocated - 3.11x more 341 | Oj.dump: 363710000 allocated - 4.19x more 342 | Rails to_json: 558952520 allocated - 6.45x more 343 | --------------------------------------------- 344 | 345 | Warming up -------------------------------------- 346 | Rails to_json 147.000 i/100ms 347 | msgpack 439.000 i/100ms 348 | Oj.dump 447.000 i/100ms 349 | Oj::Rails.encode 1.706k i/100ms 350 | Calculating ------------------------------------- 351 | Rails to_json 2.704k (±11.1%) i/s - 13.377k in 5.009333s 352 | msgpack 6.756k (±16.6%) i/s - 32.925k in 5.011767s 353 | Oj.dump 5.743k (±12.7%) i/s - 28.608k in 5.058290s 354 | Oj::Rails.encode 16.636k (±15.2%) i/s - 81.888k in 5.075079s 355 | 356 | Comparison: 357 | Oj::Rails.encode: 16635.9 i/s 358 | msgpack: 6755.8 i/s - 2.46x slower 359 | Oj.dump: 5743.1 i/s - 2.90x slower 360 | Rails to_json: 2704.3 i/s - 6.15x slower 361 | 362 | 363 | SUCCESS gemfile: gemfiles/4.2.8.gemfile rvm: 2.3.3 364 | START gemfile: gemfiles/4.2.8.gemfile rvm: 2.4.0 365 | bundle install --deployment --path /ruby-json-benchmark/vendor/bundle --quiet 366 | bundle exec ruby compatibility_test.rb && bundle exec ruby benchmark.rb 367 | 368 | Comparing Rails to_json with other JSON implementations 369 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 370 | | class | JSON to_json | Oj.dump | Oj::Rails.encode | Oj to_json | msgpack "rails" | 371 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 372 | | Regexp | 👌 | 👌 | 👌 | 👌 | 👌 | 373 | | FalseClass | 👌 | 👌 | 👌 | 👌 | 👌 | 374 | | NilClass | 👌 | 👌 | 👌 | 👌 | 👌 | 375 | | Object | ❌ | 👌 | 👌 | 👌 | 👌 | 376 | | TrueClass | 👌 | 👌 | 👌 | 👌 | 👌 | 377 | | String | 👌 | 👌 | 👌 | 👌 | 👌 | 378 | | StringChinese | 👌 | 👌 | 👌 | 👌 | 👌 | 379 | | StringSpecial | ❌ | 👌 | 👌 | 👌 | 👌 | 380 | | StringSpecial2 | 👌 | 👌 | 👌 | 👌 | 👌 | 381 | | StringSpecial3 | 👌 | 👌 | 👌 | 👌 | 👌 | 382 | | Numeric | 👌 | 👌 | 👌 | 👌 | 👌 | 383 | | Symbol | 👌 | 👌 | 👌 | 👌 | 👌 | 384 | | Time | ❌ | 👌 | 👌 | 👌 | 👌 | 385 | | Array | 👌 | 👌 | 👌 | 👌 | 👌 | 386 | | Hash | 👌 | 👌 | 👌 | 👌 | 👌 | 387 | | HashNotEmpty | 👌 | 👌 | 👌 | 👌 | 👌 | 388 | | Date | 👌 | 👌 | 👌 | 👌 | 👌 | 389 | | DateTime | ❌ | 👌 | 👌 | 👌 | 👌 | 390 | | Enumerable | ❌ | 👌 | 👌 | 👌 | 👌 | 391 | | BigDecimal | ❌ | 👌 | 👌 | 👌 | 👌 | 392 | | BigDecimalInfinity | ❌ | 👌 | 👌 | 👌 | 👌 | 393 | | Struct | ❌ | 👌 | 👌 | 👌 | 👌 | 394 | | Float | 👌 | 👌 | 👌 | 👌 | 👌 | 395 | | FloatInfinity | 💀 | 👌 | 👌 | 👌 | ❌ | 396 | | Range | 👌 | 👌 | 👌 | 👌 | 👌 | 397 | | Complex | 👌 | 👌 | 👌 | 👌 | 👌 | 398 | | Exception | ❌ | 👌 | 👌 | 👌 | 👌 | 399 | | OpenStruct | ❌ | 👌 | 👌 | 👌 | 👌 | 400 | | Rational | 👌 | 👌 | 👌 | 👌 | 👌 | 401 | | Process::Status | ❌ | 👌 | 👌 | 👌 | 👌 | 402 | | AsJson | ❌ | 👌 | 👌 | 👌 | 👌 | 403 | | ToJson | 👌 | ❌ | ❌ | 👌 | ❌ | 404 | | ActiveSupport::TimeWithZone | ❌ | 👌 | 👌 | 👌 | 👌 | 405 | | ActiveModel::Errors | ❌ | 👌 | 👌 | 👌 | 👌 | 406 | | ActiveSupport::Duration | ❌ | 👌 | 👌 | 👌 | 👌 | 407 | | ActiveSupport::Multibyte::Chars | ❌ | 👌 | 👌 | 👌 | 👌 | 408 | | ActiveRecord::Relation | ❌ | 👌 | 👌 | 👌 | 👌 | 409 | | ActiveRecord | ❌ | 💀 | 👌 | 👌 | 👌 | 410 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 411 | 412 | Calculating ------------------------------------- 413 | Rails to_json 544.812M memsize ( 536.000 retained) 414 | 11.220M objects ( 6.000 retained) 415 | 50.000 strings ( 0.000 retained) 416 | msgpack 251.049M memsize ( 9.312k retained) 417 | 4.540M objects ( 21.000 retained) 418 | 50.000 strings ( 0.000 retained) 419 | Oj.dump 336.940M memsize ( 0.000 retained) 420 | 5.520M objects ( 0.000 retained) 421 | 50.000 strings ( 0.000 retained) 422 | Oj::Rails.encode 79.680M memsize ( 192.000 retained) 423 | 1.410M objects ( 1.000 retained) 424 | 23.000 strings ( 0.000 retained) 425 | 426 | Comparison: 427 | Oj::Rails.encode: 79680192 allocated 428 | msgpack: 251049312 allocated - 3.15x more 429 | Oj.dump: 336940000 allocated - 4.23x more 430 | Rails to_json: 544812272 allocated - 6.84x more 431 | --------------------------------------------- 432 | 433 | Warming up -------------------------------------- 434 | Rails to_json 305.000 i/100ms 435 | msgpack 758.000 i/100ms 436 | Oj.dump 640.000 i/100ms 437 | Oj::Rails.encode 2.008k i/100ms 438 | Calculating ------------------------------------- 439 | Rails to_json 2.972k (± 4.8%) i/s - 14.945k in 5.039133s 440 | msgpack 7.357k (± 9.0%) i/s - 37.142k in 5.092328s 441 | Oj.dump 6.427k (± 8.4%) i/s - 32.000k in 5.019711s 442 | Oj::Rails.encode 20.084k (± 4.4%) i/s - 100.400k in 5.008269s 443 | 444 | Comparison: 445 | Oj::Rails.encode: 20083.7 i/s 446 | msgpack: 7356.5 i/s - 2.73x slower 447 | Oj.dump: 6427.0 i/s - 3.12x slower 448 | Rails to_json: 2972.5 i/s - 6.76x slower 449 | 450 | 451 | SUCCESS gemfile: gemfiles/4.2.8.gemfile rvm: 2.4.0 452 | START gemfile: gemfiles/5.0.2.gemfile rvm: 2.2.6 453 | bundle install --deployment --path /ruby-json-benchmark/vendor/bundle --quiet 454 | bundle exec ruby compatibility_test.rb && bundle exec ruby benchmark.rb 455 | 456 | Comparing Rails to_json with other JSON implementations 457 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 458 | | class | JSON to_json | Oj.dump | Oj::Rails.encode | Oj to_json | msgpack "rails" | 459 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 460 | | Regexp | 👌 | 👌 | 👌 | 👌 | 👌 | 461 | | FalseClass | 👌 | 👌 | 👌 | 👌 | 👌 | 462 | | NilClass | 👌 | 👌 | 👌 | 👌 | 👌 | 463 | | Object | ❌ | 👌 | 👌 | 👌 | 👌 | 464 | | TrueClass | 👌 | 👌 | 👌 | 👌 | 👌 | 465 | | String | 👌 | 👌 | 👌 | 👌 | 👌 | 466 | | StringChinese | 👌 | 👌 | 👌 | 👌 | 👌 | 467 | | StringSpecial | ❌ | 👌 | 👌 | 👌 | 👌 | 468 | | StringSpecial2 | 👌 | 👌 | 👌 | 👌 | 👌 | 469 | | StringSpecial3 | 👌 | 👌 | 👌 | 👌 | 👌 | 470 | | Numeric | 👌 | 👌 | 👌 | 👌 | 👌 | 471 | | Symbol | 👌 | 👌 | 👌 | 👌 | 👌 | 472 | | Time | ❌ | 👌 | 👌 | 👌 | 👌 | 473 | | Array | 👌 | 👌 | 👌 | 👌 | 👌 | 474 | | Hash | 👌 | 👌 | 👌 | 👌 | 👌 | 475 | | HashNotEmpty | 👌 | 👌 | 👌 | 👌 | 👌 | 476 | | Date | 👌 | 👌 | 👌 | 👌 | 👌 | 477 | | DateTime | ❌ | 👌 | 👌 | 👌 | 👌 | 478 | | Enumerable | ❌ | 👌 | 👌 | 👌 | 👌 | 479 | | BigDecimal | ❌ | 👌 | 👌 | 👌 | 👌 | 480 | | BigDecimalInfinity | ❌ | 👌 | 👌 | 👌 | 👌 | 481 | | Struct | ❌ | 👌 | 👌 | 👌 | 👌 | 482 | | Float | 👌 | 👌 | 👌 | 👌 | 👌 | 483 | | FloatInfinity | 💀 | 👌 | 👌 | 👌 | ❌ | 484 | | Range | 👌 | 👌 | 👌 | 👌 | 👌 | 485 | | Complex | 👌 | 👌 | 👌 | 👌 | 👌 | 486 | | Exception | 👌 | 👌 | 👌 | 👌 | 👌 | 487 | | OpenStruct | ❌ | 👌 | 👌 | 👌 | 👌 | 488 | | Rational | 👌 | 👌 | 👌 | 👌 | 👌 | 489 | | Process::Status | ❌ | 👌 | 👌 | 👌 | 👌 | 490 | | AsJson | ❌ | 👌 | 👌 | 👌 | 👌 | 491 | | ToJson | 👌 | ❌ | ❌ | 👌 | ❌ | 492 | | ActiveSupport::TimeWithZone | ❌ | 👌 | 👌 | 👌 | 👌 | 493 | | ActiveModel::Errors | ❌ | 👌 | 👌 | 👌 | 👌 | 494 | | ActiveSupport::Duration | ❌ | 👌 | 👌 | 👌 | 👌 | 495 | | ActiveSupport::Multibyte::Chars | ❌ | 👌 | 👌 | 👌 | 👌 | 496 | | ActiveRecord::Relation | ❌ | 👌 | 👌 | 👌 | 👌 | 497 | | ActiveRecord | ❌ | 👌 | 👌 | 👌 | 👌 | 498 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 499 | 500 | Calculating ------------------------------------- 501 | Rails to_json 557.443M memsize ( 464.000 retained) 502 | 11.280M objects ( 7.000 retained) 503 | 50.000 strings ( 1.000 retained) 504 | msgpack 269.030M memsize ( 232.000 retained) 505 | 4.630M objects ( 1.000 retained) 506 | 50.000 strings ( 0.000 retained) 507 | Oj.dump 363.400M memsize ( 0.000 retained) 508 | 5.610M objects ( 0.000 retained) 509 | 50.000 strings ( 0.000 retained) 510 | Oj::Rails.encode 83.610M memsize ( 0.000 retained) 511 | 1.440M objects ( 0.000 retained) 512 | 26.000 strings ( 0.000 retained) 513 | 514 | Comparison: 515 | Oj::Rails.encode: 83610000 allocated 516 | msgpack: 269030232 allocated - 3.22x more 517 | Oj.dump: 363400000 allocated - 4.35x more 518 | Rails to_json: 557442848 allocated - 6.67x more 519 | --------------------------------------------- 520 | 521 | Warming up -------------------------------------- 522 | Rails to_json 265.000 i/100ms 523 | msgpack 615.000 i/100ms 524 | Oj.dump 558.000 i/100ms 525 | Oj::Rails.encode 1.706k i/100ms 526 | Calculating ------------------------------------- 527 | Rails to_json 2.694k (± 4.4%) i/s - 13.515k in 5.026013s 528 | msgpack 6.855k (± 6.3%) i/s - 34.440k in 5.044588s 529 | Oj.dump 6.064k (± 4.8%) i/s - 30.690k in 5.072408s 530 | Oj::Rails.encode 17.715k (± 4.0%) i/s - 88.712k in 5.015543s 531 | 532 | Comparison: 533 | Oj::Rails.encode: 17715.0 i/s 534 | msgpack: 6854.7 i/s - 2.58x slower 535 | Oj.dump: 6064.2 i/s - 2.92x slower 536 | Rails to_json: 2694.2 i/s - 6.58x slower 537 | 538 | 539 | SUCCESS gemfile: gemfiles/5.0.2.gemfile rvm: 2.2.6 540 | START gemfile: gemfiles/5.0.2.gemfile rvm: 2.3.3 541 | bundle install --deployment --path /ruby-json-benchmark/vendor/bundle --quiet 542 | bundle exec ruby compatibility_test.rb && bundle exec ruby benchmark.rb 543 | 544 | Comparing Rails to_json with other JSON implementations 545 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 546 | | class | JSON to_json | Oj.dump | Oj::Rails.encode | Oj to_json | msgpack "rails" | 547 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 548 | | Regexp | 👌 | 👌 | 👌 | 👌 | 👌 | 549 | | FalseClass | 👌 | 👌 | 👌 | 👌 | 👌 | 550 | | NilClass | 👌 | 👌 | 👌 | 👌 | 👌 | 551 | | Object | ❌ | 👌 | 👌 | 👌 | 👌 | 552 | | TrueClass | 👌 | 👌 | 👌 | 👌 | 👌 | 553 | | String | 👌 | 👌 | 👌 | 👌 | 👌 | 554 | | StringChinese | 👌 | 👌 | 👌 | 👌 | 👌 | 555 | | StringSpecial | ❌ | 👌 | 👌 | 👌 | 👌 | 556 | | StringSpecial2 | 👌 | 👌 | 👌 | 👌 | 👌 | 557 | | StringSpecial3 | 👌 | 👌 | 👌 | 👌 | 👌 | 558 | | Numeric | 👌 | 👌 | 👌 | 👌 | 👌 | 559 | | Symbol | 👌 | 👌 | 👌 | 👌 | 👌 | 560 | | Time | ❌ | 👌 | 👌 | 👌 | 👌 | 561 | | Array | 👌 | 👌 | 👌 | 👌 | 👌 | 562 | | Hash | 👌 | 👌 | 👌 | 👌 | 👌 | 563 | | HashNotEmpty | 👌 | 👌 | 👌 | 👌 | 👌 | 564 | | Date | 👌 | 👌 | 👌 | 👌 | 👌 | 565 | | DateTime | ❌ | 👌 | 👌 | 👌 | 👌 | 566 | | Enumerable | ❌ | 👌 | 👌 | 👌 | 👌 | 567 | | BigDecimal | ❌ | 👌 | 👌 | 👌 | 👌 | 568 | | BigDecimalInfinity | ❌ | 👌 | 👌 | 👌 | 👌 | 569 | | Struct | ❌ | 👌 | 👌 | 👌 | 👌 | 570 | | Float | 👌 | 👌 | 👌 | 👌 | 👌 | 571 | | FloatInfinity | 💀 | 👌 | 👌 | 👌 | ❌ | 572 | | Range | 👌 | 👌 | 👌 | 👌 | 👌 | 573 | | Complex | 👌 | 👌 | 👌 | 👌 | 👌 | 574 | | Exception | 👌 | 👌 | 👌 | 👌 | 👌 | 575 | | OpenStruct | ❌ | 👌 | 👌 | 👌 | 👌 | 576 | | Rational | 👌 | 👌 | 👌 | 👌 | 👌 | 577 | | Process::Status | ❌ | 👌 | 👌 | 👌 | 👌 | 578 | | AsJson | ❌ | 👌 | 👌 | 👌 | 👌 | 579 | | ToJson | 👌 | ❌ | ❌ | 👌 | ❌ | 580 | | ActiveSupport::TimeWithZone | ❌ | 👌 | 👌 | 👌 | 👌 | 581 | | ActiveModel::Errors | ❌ | 👌 | 👌 | 👌 | 👌 | 582 | | ActiveSupport::Duration | ❌ | 👌 | 👌 | 👌 | 👌 | 583 | | ActiveSupport::Multibyte::Chars | ❌ | 👌 | 👌 | 👌 | 👌 | 584 | | ActiveRecord::Relation | ❌ | 👌 | 👌 | 👌 | 👌 | 585 | | ActiveRecord | ❌ | 👌 | 👌 | 👌 | 👌 | 586 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 587 | 588 | Calculating ------------------------------------- 589 | Rails to_json 554.243M memsize ( 464.000 retained) 590 | 11.200M objects ( 7.000 retained) 591 | 50.000 strings ( 1.000 retained) 592 | msgpack 263.441M memsize ( 10.952k retained) 593 | 4.490M objects ( 21.000 retained) 594 | 50.000 strings ( 0.000 retained) 595 | Oj.dump 358.200M memsize ( 0.000 retained) 596 | 5.480M objects ( 0.000 retained) 597 | 50.000 strings ( 0.000 retained) 598 | Oj::Rails.encode 84.810M memsize ( 0.000 retained) 599 | 1.470M objects ( 0.000 retained) 600 | 28.000 strings ( 0.000 retained) 601 | 602 | Comparison: 603 | Oj::Rails.encode: 84810000 allocated 604 | msgpack: 263440952 allocated - 3.11x more 605 | Oj.dump: 358200000 allocated - 4.22x more 606 | Rails to_json: 554242848 allocated - 6.54x more 607 | --------------------------------------------- 608 | 609 | Warming up -------------------------------------- 610 | Rails to_json 174.000 i/100ms 611 | msgpack 499.000 i/100ms 612 | Oj.dump 335.000 i/100ms 613 | Oj::Rails.encode 1.737k i/100ms 614 | Calculating ------------------------------------- 615 | Rails to_json 2.619k (±11.3%) i/s - 13.050k in 5.050032s 616 | msgpack 7.210k (±19.6%) i/s - 34.930k in 5.040792s 617 | Oj.dump 5.973k (±17.3%) i/s - 29.145k in 5.032593s 618 | Oj::Rails.encode 18.352k (± 7.5%) i/s - 92.061k in 5.044822s 619 | 620 | Comparison: 621 | Oj::Rails.encode: 18352.3 i/s 622 | msgpack: 7210.2 i/s - 2.55x slower 623 | Oj.dump: 5973.0 i/s - 3.07x slower 624 | Rails to_json: 2618.7 i/s - 7.01x slower 625 | 626 | 627 | SUCCESS gemfile: gemfiles/5.0.2.gemfile rvm: 2.3.3 628 | START gemfile: gemfiles/5.0.2.gemfile rvm: 2.4.0 629 | bundle install --deployment --path /ruby-json-benchmark/vendor/bundle --quiet 630 | bundle exec ruby compatibility_test.rb && bundle exec ruby benchmark.rb 631 | 632 | Comparing Rails to_json with other JSON implementations 633 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 634 | | class | JSON to_json | Oj.dump | Oj::Rails.encode | Oj to_json | msgpack "rails" | 635 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 636 | | Regexp | 👌 | 👌 | 👌 | 👌 | 👌 | 637 | | FalseClass | 👌 | 👌 | 👌 | 👌 | 👌 | 638 | | NilClass | 👌 | 👌 | 👌 | 👌 | 👌 | 639 | | Object | ❌ | 👌 | 👌 | 👌 | 👌 | 640 | | TrueClass | 👌 | 👌 | 👌 | 👌 | 👌 | 641 | | String | 👌 | 👌 | 👌 | 👌 | 👌 | 642 | | StringChinese | 👌 | 👌 | 👌 | 👌 | 👌 | 643 | | StringSpecial | ❌ | 👌 | 👌 | 👌 | 👌 | 644 | | StringSpecial2 | 👌 | 👌 | 👌 | 👌 | 👌 | 645 | | StringSpecial3 | 👌 | 👌 | 👌 | 👌 | 👌 | 646 | | Numeric | 👌 | 👌 | 👌 | 👌 | 👌 | 647 | | Symbol | 👌 | 👌 | 👌 | 👌 | 👌 | 648 | | Time | ❌ | 👌 | 👌 | 👌 | 👌 | 649 | | Array | 👌 | 👌 | 👌 | 👌 | 👌 | 650 | | Hash | 👌 | 👌 | 👌 | 👌 | 👌 | 651 | | HashNotEmpty | 👌 | 👌 | 👌 | 👌 | 👌 | 652 | | Date | 👌 | 👌 | 👌 | 👌 | 👌 | 653 | | DateTime | ❌ | 👌 | 👌 | 👌 | 👌 | 654 | | Enumerable | ❌ | 👌 | 👌 | 👌 | 👌 | 655 | | BigDecimal | ❌ | 👌 | 👌 | 👌 | 👌 | 656 | | BigDecimalInfinity | ❌ | 👌 | 👌 | 👌 | 👌 | 657 | | Struct | ❌ | 👌 | 👌 | 👌 | 👌 | 658 | | Float | 👌 | 👌 | 👌 | 👌 | 👌 | 659 | | FloatInfinity | 💀 | 👌 | 👌 | 👌 | ❌ | 660 | | Range | 👌 | 👌 | 👌 | 👌 | 👌 | 661 | | Complex | 👌 | 👌 | 👌 | 👌 | 👌 | 662 | | Exception | 👌 | 👌 | 👌 | 👌 | 👌 | 663 | | OpenStruct | ❌ | 👌 | 👌 | 👌 | 👌 | 664 | | Rational | 👌 | 👌 | 👌 | 👌 | 👌 | 665 | | Process::Status | ❌ | 👌 | 👌 | 👌 | 👌 | 666 | | AsJson | ❌ | 👌 | 👌 | 👌 | 👌 | 667 | | ToJson | 👌 | ❌ | ❌ | 👌 | ❌ | 668 | | ActiveSupport::TimeWithZone | ❌ | 👌 | 👌 | 👌 | 👌 | 669 | | ActiveModel::Errors | ❌ | 👌 | 👌 | 👌 | 👌 | 670 | | ActiveSupport::Duration | ❌ | 👌 | 👌 | 👌 | 👌 | 671 | | ActiveSupport::Multibyte::Chars | ❌ | 👌 | 👌 | 👌 | 👌 | 672 | | ActiveRecord::Relation | ❌ | 👌 | 👌 | 👌 | 👌 | 673 | | ActiveRecord | ❌ | 👌 | 👌 | 👌 | 👌 | 674 | +---------------------------------+--------------+---------+------------------+------------+-----------------+ 675 | 676 | Calculating ------------------------------------- 677 | Rails to_json 540.903M memsize ( 656.000 retained) 678 | 11.120M objects ( 8.000 retained) 679 | 50.000 strings ( 1.000 retained) 680 | msgpack 245.949M memsize ( 9.312k retained) 681 | 4.410M objects ( 21.000 retained) 682 | 50.000 strings ( 0.000 retained) 683 | Oj.dump 332.230M memsize ( 0.000 retained) 684 | 5.400M objects ( 0.000 retained) 685 | 50.000 strings ( 0.000 retained) 686 | Oj::Rails.encode 77.770M memsize ( 192.000 retained) 687 | 1.360M objects ( 1.000 retained) 688 | 24.000 strings ( 0.000 retained) 689 | 690 | Comparison: 691 | Oj::Rails.encode: 77770192 allocated 692 | msgpack: 245949312 allocated - 3.16x more 693 | Oj.dump: 332230000 allocated - 4.27x more 694 | Rails to_json: 540902520 allocated - 6.96x more 695 | --------------------------------------------- 696 | 697 | Warming up -------------------------------------- 698 | Rails to_json 265.000 i/100ms 699 | msgpack 676.000 i/100ms 700 | Oj.dump 538.000 i/100ms 701 | Oj::Rails.encode 1.680k i/100ms 702 | Calculating ------------------------------------- 703 | Rails to_json 2.251k (±17.5%) i/s - 11.130k in 5.145463s 704 | msgpack 6.051k (±12.0%) i/s - 29.744k in 5.005225s 705 | Oj.dump 5.385k (± 9.2%) i/s - 26.900k in 5.043975s 706 | Oj::Rails.encode 17.472k (±13.1%) i/s - 85.680k in 5.030475s 707 | 708 | Comparison: 709 | Oj::Rails.encode: 17472.0 i/s 710 | msgpack: 6050.6 i/s - 2.89x slower 711 | Oj.dump: 5384.6 i/s - 3.24x slower 712 | Rails to_json: 2251.0 i/s - 7.76x slower 713 | 714 | 715 | SUCCESS gemfile: gemfiles/5.0.2.gemfile rvm: 2.4.0 716 | rm -rf .bundle 717 | 718 | Results: 719 | SUCCESS gemfile: gemfiles/4.1.16.gemfile rvm: 2.2.6 720 | SUCCESS gemfile: gemfiles/4.1.16.gemfile rvm: 2.3.3 721 | FAILURE gemfile: gemfiles/4.1.16.gemfile rvm: 2.4.0 722 | SUCCESS gemfile: gemfiles/4.2.8.gemfile rvm: 2.2.6 723 | SUCCESS gemfile: gemfiles/4.2.8.gemfile rvm: 2.3.3 724 | SUCCESS gemfile: gemfiles/4.2.8.gemfile rvm: 2.4.0 725 | SUCCESS gemfile: gemfiles/5.0.2.gemfile rvm: 2.2.6 726 | SUCCESS gemfile: gemfiles/5.0.2.gemfile rvm: 2.3.3 727 | SUCCESS gemfile: gemfiles/5.0.2.gemfile rvm: 2.4.0 728 | 729 | Failed: 730 | BUNDLE_GEMFILE=gemfiles/4.1.16.gemfile RBENV_VERSION=2.4.0 bundle exec ruby compatibility_test.rb && bundle exec ruby benchmark.rb 731 | --------------------------------------------------------------------------------