なろう分析記録

『小説家になろう』をふくめ『ネット小説投稿サイト』を分析する。コード置き場,主にPython,javascript,たまに創作。

Pythonの変数を一時書き出ししておく「joblib」と「pickle」を徹底的に比較する。

Pythonの変数をそのまま一時保存しておきたい

Pythonのオブジェクトを一時的に保存しおく方法には「csv書き出し」や「pickle」を使うなどの方法があります。

しかし「csvでは読み書きの作業が面倒」「pickleではファイルサイズが大きくなりがち」という問題があります。

そこで「joblib」です。

ここでは「joblib.dump」を使ったリストの書き出しと「joblib.load」を使った読み込みについて解説します。

また「joblib」と「pickle」についてファイルサイズや処理時間などを比較してみたいと思います。

準備

pip install joblib

これだけです。

「joblib」の使用方法

書き出し

import sys
sys.setrecursionlimit(10000)#エラー回避
import joblib

#保存するリスト
test_list=["test","name","job"]

#書き出し処理
joblib.dump(test_list, "temp.txt",compress=3)

最初に「RuntimeError: maximum recursion depth exceeded」のエラーを回避するために再帰処理の上限を増やしています。

compress=3

では、圧縮度を設定しています。なお3以上にしてもほぼ変わらない様です。

f:id:karupoimou:20190526194700p:plain
出力ファイルを開いてみたもの

出力ファイルは圧縮されているので、テキストエディタで開いてみても内容を読み取ることは出来ません。

そこで、読み出す際には「joblib.load」を使用します。

読み出し

import sys
sys.setrecursionlimit(10000)#エラー回避
import joblib

#読み出し処理
a = joblib.load( "temp.txt")

print(a)

f:id:karupoimou:20190526195021p:plain
結果


読み出しは普通にファイルを指定するだけと非常に単純です。

「pickle」と「joblib」の比較

ファイルサイズの比較

次にpythonで一般的に使われている「pickle」と比較を行ってみたいと思います。

生成コード
import sys
sys.setrecursionlimit(10000)#エラー回避
import joblib
import pickle
import time

test_list=[]

for i in range(10000000):
    test_list.append(i)

#「joblib」での書き出し
joblib.dump(test_list, "temp_joblib.txt",compress=3)

#「pickle」での書き出し
with open('temp_pickle.txt', 'wb') as f:
    pickle.dump(test_list, f)
ファイルサイズの結果

f:id:karupoimou:20190526195951p:plain
結果

「joblib」では14876kb
「pickle」では48720kb

となり、「joblib」は「pickle」と比べて倍以上のファイルサイズ節約ができるという結果になりました。

書き込み速度の比較

「time」を使って保存及び読み出しの際の実行速度も比較してみたいと思います。

import sys
sys.setrecursionlimit(10000)#エラー回避
import joblib
import pickle
import time

test_list=[]

#読み出し処理
test_list = joblib.load( "temp.txt")

t1=time.time()

#「joblib」での書き出し処理
joblib.dump(test_list, "temp_joblib.txt",compress=3)

t2=time.time()

#「pickle」での書き出し
with open('temp_pickle.txt', 'wb') as f:
    pickle.dump(test_list, f)

t3=time.time()

print("joblib ",str(t2-t1))
print("pickle ",str(t3-t2))
書き込み速度の結果

joblib 34.55282759666443
pickle 0.5858054161071777
(秒単位)

書き込みスピードは「pickle」の方が圧倒的に早いみたいです。
やはり圧縮処理を挟むことで時間はかなりかかってしまうようですね。

f:id:karupoimou:20190526202849p:plain
書き込み時間の比較

追記
10回試行した平均を出したもの

f:id:karupoimou:20190527125056p:plain:w200
10回試行の平均

読み込み時間の比較

同じく、読み込み時間を比較してみたいと思います。

import sys
sys.setrecursionlimit(10000)#エラー回避
import joblib
import pickle
import time

t1=time.time()

#「joblib」での読み込み処理
joblib.load("temp_joblib.txt")

t2=time.time()

#「pickle」での読み込み処理
with open('temp_pickle.txt', 'rb') as f:
    a=pickle.load(f)

t3=time.time()

print("joblib ",str(t2-t1))
print("pickle ",str(t3-t2))
読み込み時間の結果

joblib 17.864126682281494
pickle 0.9516866207122803
(秒単位)

f:id:karupoimou:20190526203235p:plain
読み込み処理時間の比較

追記
10回試行の平均

f:id:karupoimou:20190527125733p:plain
 10回試行の平均

比較結果まとめ

ファイルサイズ(joblibの勝ち)
joblib=14876kb
pickle=48720kb


書き込み時間(pickleの勝ち)
joblib 34.55282759666443
pickle 0.5858054161071777


読み込み時間(pickleの勝ち)
joblib 17.864126682281494
pickle 0.9516866207122803

結論

ファイルサイズの観点からみれば「joblib」が優れており、読み書き処理時間の観点では「pickle」の方が格段に早いようです。

なのでファイルサイズが大きくなりがちな変数は「joblib」で管理し、対して大きくないファイルは「pickle」を使用するのが良さそうです。

参考ページ

PythonのPickleモジュールを理解したいだけの人生だった - Qiita

joblibのdump,load地味に便利

【Python】処理にかかる時間を計測して表示 - Qiita


joblibは、巨大なデータ構造体の配列バッファに対して特別な処理を行うため、大規模で巨大な配列では通常かなり高速です。実装の詳細については、source codeをご覧ください。zlibを使用して酸洗いしながら、そのデータをその場で圧縮することもできます。
python – joblibとpickleの異なるユースケースは何ですか? - コードログ


joblib と pickle の比較 - Tak's Notebook


Python3: 並列処理で速度を上げる Joblib | お名前.com、さくらのVPS等のサーバーでの開発・設定メモ


joblibの真髄は並列処理とのこと。
設定とマシンスペックさえあればかなり高速化できそう。