ActiveRecord의 serialize에서 MessagePack 사용

모처럼이므로 디폴트(YAML), Oj(json), MessagePack로 벤치마크도 취해 보았습니다.
저장할 데이터는 h tp // j 그런게 쥐와 r. 아 ps포 t. 코m/ 여기서 적당하게 만든 것을 로드하고 돌진하고 있습니다.
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형으로 하고 있습니다.

모델
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의 두 번째 인수로 지정

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

결과
"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 빠른!

좋은 웹페이지 즐겨찾기