copy.deepcopy()とpickle経由のコピーの速度比較
pythonのcopy.deepcopy()とpickle経由のコピーの速度を比較した。
pythonのcopy.deepcopy()に死ぬほど時間がかかるなーと思っていたら、こんなQAを見つけた。
python - copy.deepcopy vs pickle - Stack Overflow
deepcopyよりも使える場面は減るが、pickle経由で新しいオブジェクトを作ったほうが速いことがあるらしい。
簡単に実験してみた。
case | copy.copy() | copy.deepcopy() | pickle |
---|---|---|---|
1 | 0.64 ms | 303.71 ms | 6.14 ms |
2 | 1.98 ms | 1471.17 ms | 65.49 ms |
3 | 1.13 ms | 3376.47 ms | 177.26 ms |
4 | (3.14 ms) | 7585.37 ms | 326.24 ms |
5 | (0.54 ms) | 244.45 ms | 6.75 ms |
それぞれのテストケースでコピーしている内容はソースコードを参照。
copyで結果が括弧つきになっているものはdeepcopyできていないケース。
どのケースでもpickleを使ったほうがdeepcopyよりも10倍以上早くなっている。
整数のリストをコピーするだけ(case 1)でも大きく差がついている。
なんでこんなに差がつくのか気になって、cpythonの実装を調べてみた。
def _deepcopy_list(x, memo, deepcopy=deepcopy): y = [] memo[id(x)] = y append = y.append for a in x: append(deepcopy(a, memo)) return y
(参照:cpython/copy.py at 3.8 · python/cpython · GitHub)
listのコピーをappend連打で行っていた。
これは確かに時間がかかりそう。
一方、pickleの方はC言語で実装されているのでfor文がそこそこ高速に回せるということらしい。
なお、numpy.ndarrayなど高速な__deepcopy__が定義されているクラスなら、無難にdeepcopyするのが一番速いので注意。