技術

JSON vs pickle

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

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

以下、テストコード。

<br />
import timeit<br />
import json<br />
import pickle<br />
import cPickle</p>
<p>source_data = dict(id = 256, title = u'Test title.', tags = ('test', 'other', 'html'), published = True, comments = [])</p>
<p>repeat = 3<br />
loop = 100000</p>
<p>def to_json(data):<br />
	return json.dumps(data)</p>
<p>def from_json(data):<br />
	return json.loads(data)</p>
<p>def to_pickle(data):<br />
	return pickle.dumps(data, protocol = 2)</p>
<p>def from_pickle(data):<br />
	return pickle.loads(data)</p>
<p>def to_cPickle(data):<br />
	return cPickle.dumps(data, protocol = 2)</p>
<p>def from_cPickle(data):<br />
	return cPickle.loads(data)</p>
<p>print 'to_json'<br />
t = timeit.Timer('to_json(source_data)', 'from __main__ import to_json, source_data')<br />
print min(t.repeat(repeat, loop))<br />
print ''</p>
<p>print 'to_pickle'<br />
t = timeit.Timer('to_pickle(source_data)', 'from __main__ import to_pickle, source_data')<br />
print min(t.repeat(repeat, loop))<br />
print ''</p>
<p>print 'to_cPickle'<br />
t = timeit.Timer('to_cPickle(source_data)', 'from __main__ import to_cPickle, source_data')<br />
print min(t.repeat(repeat, loop))<br />
print ''</p>
<p>print 'from_json'<br />
json_data = to_json(source_data)<br />
t = timeit.Timer('from_json(json_data)', 'from __main__ import from_json, json_data')<br />
print min(t.repeat(repeat, loop))<br />
print ''</p>
<p>print 'from_pickle'<br />
pickle_data = to_pickle(source_data)<br />
t = timeit.Timer('from_pickle(pickle_data)', 'from __main__ import from_pickle, pickle_data')<br />
print min(t.repeat(repeat, loop))<br />
print ''</p>
<p>print 'from_cPickle'<br />
cPickle_data = to_cPickle(source_data)<br />
t = timeit.Timer('from_cPickle(cPickle_data)', 'from __main__ import from_cPickle, cPickle_data')<br />
print min(t.repeat(repeat, loop))<br />
print ''<br />

実行結果(Python2.7使用)

<br />
to_json<br />
1.91382908821</p>
<p>to_pickle<br />
16.7020881176</p>
<p>to_cPickle<br />
0.530957937241</p>
<p>from_json<br />
2.18486499786</p>
<p>from_pickle<br />
9.6311609745</p>
<p>from_cPickle<br />
0.661497116089<br />

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

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

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

コメントを残す

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



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

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください