技術

JSON vs pickle

最近よく複雑なオブジェクトの保存のためにJSONを使っています。
人間にも読みやすいのでテストやデバッグに便利です。

しかしWebサービス等で使うとなると使い方にもよりますが、物凄い回数オブジェクト→JSONとかJSON→オブジェクトとかの変換が行われる事になります。
JSONよりも読みづらくなりますが、専用のバイナリデータを扱うpickleならもっと速いんじゃないか?ということで調べてみました。

以下、テストコード。

import timeit
import json
import pickle
import cPickle

source_data = dict(id = 256, title = u'Test title.', tags = ('test', 'other', 'html'), published = True, comments = [])

repeat = 3
loop = 100000

def to_json(data):
	return json.dumps(data)

def from_json(data):
	return json.loads(data)

def to_pickle(data):
	return pickle.dumps(data, protocol = 2)

def from_pickle(data):
	return pickle.loads(data)

def to_cPickle(data):
	return cPickle.dumps(data, protocol = 2)

def from_cPickle(data):
	return cPickle.loads(data)

print 'to_json'
t = timeit.Timer('to_json(source_data)', 'from __main__ import to_json, source_data')
print min(t.repeat(repeat, loop))
print ''

print 'to_pickle'
t = timeit.Timer('to_pickle(source_data)', 'from __main__ import to_pickle, source_data')
print min(t.repeat(repeat, loop))
print ''

print 'to_cPickle'
t = timeit.Timer('to_cPickle(source_data)', 'from __main__ import to_cPickle, source_data')
print min(t.repeat(repeat, loop))
print ''

print 'from_json'
json_data = to_json(source_data)
t = timeit.Timer('from_json(json_data)', 'from __main__ import from_json, json_data')
print min(t.repeat(repeat, loop))
print ''

print 'from_pickle'
pickle_data = to_pickle(source_data)
t = timeit.Timer('from_pickle(pickle_data)', 'from __main__ import from_pickle, pickle_data')
print min(t.repeat(repeat, loop))
print ''

print 'from_cPickle'
cPickle_data = to_cPickle(source_data)
t = timeit.Timer('from_cPickle(cPickle_data)', 'from __main__ import from_cPickle, cPickle_data')
print min(t.repeat(repeat, loop))
print ''

実行結果(Python2.7使用)

to_json
1.91382908821

to_pickle
16.7020881176

to_cPickle
0.530957937241

from_json
2.18486499786

from_pickle
9.6311609745

from_cPickle
0.661497116089

pickle遅いです。
というかjson速いです。
cPickleと比べてこの速度差なら、自分の典型的な作成パターンだとデバッグのしやすさを考えてとりあえずjsonですね。
速度に我慢ならなくなったらcPickle。

しかしそれぞれメリット・デメリットありますので使い道次第です。

jsonモジュール
  • メリット
    ダンプ結果がとても読みやすい
  • デメリット
    素のままでdump&loadできる型が辞書、リスト、文字列、整数、浮動小数点数、True、False、Noneに限られる。
    (ただしやろうと思えば普通に特定の型のカスタムエンコーダ・デコーダを実装して追加できる。)
pickleモジュール
  • メリット
    基本的にどんな型でもダンプできる。(各モジュールのトップレベルで定義されてない関数やクラス等はそのままではダンプできないらしいけど。)
    pickle 化や unpickle 化を行うカスタムのサブクラスを導出することができる。
    バイナリ化できるので容量を食わないかも。(まぁこの点はXMLと比べたらJSONも全然マシだと思います)
  • デメリット
    遅い
cPickleモジュール
  • メリット
    基本的にどんな型でもダンプできる。(各モジュールのトップレベルで定義されてない関数やクラス等は以下略)
    バイナリ化するので容量を食わない。(まぁこの点はXMLと比べたら以下略)
    速い
  • デメリット
    pickle 化や unpickle 化を行うカスタムのサブクラスを導出することができない。

コメントを残す

メールアドレスが公開されることはありません。



※画像をクリックして別の画像を表示