はじめに
Pythonにはpickle(cPickle)という、オブジェクトの直列化モジュールがあります。
pickleはとても有名だと思います。
実は、似たようなモジュールとしてmarshalというのもあります。
こちらはあまり有名ではありませんね。
永続化してくれるモジュールではありませんし、バージョン間の互換性も保証されていませんので、わざわざmarshalを使う理由がありませんからね。有名ではないのも当然です。
pickleに比べて欠点だらけのmarshalですが、marshalにも良いところがあることが分かりましたので、今回はそれをテーマにします。
marshalの良いところ、それは「速度」です。
速度をチェック
早速、書き出しと読み込みの速度をチェックしてみましょう。
今回、速度を比較したのは「cPickle」と「marshal」です。
まずは書き出し。
#!/usr/bin/env python
# -- coding:utf-8 -*-
import marshal
import cPickle as pickle
import time
import numpy as np
def main():
a = np.ndarray(shape=(10000, 10000))
start = time.time()
pickle.dump(a, open('output.pkl', 'wb'))
p_time = time.time() - start
start = time.time()
marshal.dump(a, open('output.msl', 'wb'))
m_time = time.time() - start
print p_time, m_time
if __name__ == '__main__':
main()
コードはこんな感じです。
多次元配列を生成して、それを書き出しています。
それでは出力を見てみましょう。
143.123441935 5.09839010239
左がcPickle、右がmarshalで、単位は秒です。
思っていたよりも差が出ましたね、予想外でした。
次は読み込み。
#!/usr/bin/env python
# -- coding:utf-8 -*-
import marshal
import cPickle as pickle
import time
import numpy as np
def main():
start = time.time()
a = pickle.load(open('output.pkl', 'rb'))
p_time = time.time() - start
start = time.time()
b = marshal.load(open('output.msl', 'rb'))
m_time = time.time() - start
print p_time, m_time
if __name__ == '__main__':
main()
コードはこれです。
dumpをloadにしているだけです。
結果がこちら
445.698551893 1.64994597435
同じく左がcPickle、右がmarshal、単位は秒です。
いやぁ、すごい差ですね……、かなり驚いています。
まとめ
はい。というわけで速度ではmarshalがはやいということが分かりました。
なんででしょうか、理由は調べていません。
しかしながら、速度ではmarshalが勝っていますが、永続化してくれるpickleの方が圧倒的に便利なので使うならやっぱりpickleですね。
だったらなんで比較したんだって話ですね。
理由としては、気になったからという他ありません。
というわけで、ほとんど使うことのないであろうmarshalにスポットを当てたよ!、という話は以上になります。