LoginSignup
6
6

More than 5 years have passed since last update.

ActiveRecordのserializeでMessagePackを使う

Last updated at Posted at 2015-07-05

せっかくなのでデフォルト(YAML)、Oj(json)、MessagePackでベンチマークも取ってみました。
保存するデータは http://json-generator.appspot.com/ ここで適当に作ったものをロードして突っ込んでます。
DBに保存していたりしますが、単純にそれぞれのdumpとloadの差です。

migration
create_table :articles, force: true do |t|
  t.column :body, "MEDIUMTEXT", null: false
  t.timestamps null: false
end

create_table :oj_articles, force: true do |t|
  t.column :body, "MEDIUMTEXT", null: false
  t.timestamps null: false
end

create_table :msgpack_articles, force: true do |t|
  t.column :body, "MEDIUMBLOB", null: false
  t.timestamps null: false
  end

MessagePackはバイナリデータなので、BLOB型にしています。

models
class SerializationOj
  def self.dump(obj)
    Oj.dump(obj, mode: :compat)
  end

  def self.load(json)
    Oj.load(json, mode: :compat) unless json.nil?
  end
end

class SerializationMessagePack
  def self.dump(obj)
    MessagePack.pack(obj)
  end

  def self.load(binary)
    MessagePack.unpack(binary) unless binary.nil?
  end
end

class Article < ActiveRecord::Base
  serialize :body
end

class OjArticle < ActiveRecord::Base
  serialize :body, SerializationOj
end

class MsgpackArticle < ActiveRecord::Base
  serialize :body, SerializationMessagePack
end

MessagePackのシリアライズクラスを作ってserializeの第2引数に指定

benchmark
BENCH_TIMES = 10000
BODY_DATA   = Oj.load(File.read(File.expand_path("../dummy.json", __FILE__)), mode: :compat)

p "file size: #{BODY_DATA.size}"

Benchmark.bmbm do |bm|
  p "yaml"
  bm.report "create" do
    BENCH_TIMES.times do
      Article.create!(body: BODY_DATA)
    end
  end

  bm.report "find" do
    BENCH_TIMES.times do
      Article.limit(100).collect(&:body)
    end
  end
end

Benchmark.bmbm do |bm|
  p "oj"
  bm.report "create" do
    BENCH_TIMES.times do
      OjArticle.create!(body: BODY_DATA)
    end
  end

  bm.report "find" do
    BENCH_TIMES.times do
      OjArticle.limit(100).collect(&:body)
    end
  end
end

Benchmark.bmbm do |bm|
  p "msgpack"
  bm.report "create" do
    BENCH_TIMES.times do
      MsgpackArticle.create!(body: BODY_DATA)
    end
  end

  bm.report "find" do
    BENCH_TIMES.times do
      MsgpackArticle.limit(100).collect(&:body)
    end
  end
end
result
"file size: 87505"

"yaml"
Rehearsal ------------------------------------------
create 194.760000   4.410000 199.170000 (226.059458)
find   1443.380000 145.550000 1588.930000 (1691.537545)
------------------------------ total: 1788.100000sec

             user     system      total        real
create 194.280000   4.370000 198.650000 (249.059130)
find   1443.510000 145.030000 1588.540000 (1690.263404)


"oj"
Rehearsal ------------------------------------------
create  50.360000   3.440000  53.800000 ( 83.307643)
find   392.770000 137.870000 530.640000 (633.403793)
------------------------------- total: 584.440000sec

             user     system      total        real
create  50.550000   3.320000  53.870000 (116.603378)
find   393.820000 138.790000 532.610000 (635.451361)


"msgpack"
Rehearsal ------------------------------------------
create  13.390000   3.490000  16.880000 ( 39.246475)
find    75.450000 103.490000 178.940000 (268.235375)
------------------------------- total: 195.820000sec

             user     system      total        real
create  15.200000   3.670000  18.870000 (147.845164)
find    75.580000 104.860000 180.440000 (269.350645)

MsagePack速い! :stuck_out_tongue_closed_eyes:

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6