実験環境
OS |
macOS Sierra |
CPU |
2.3 GHz Intel Core i7 |
メモリ |
16 GB 1600 MHz DDR3 |
Pythonのバージョン |
2.7.10 |
実験
準備
- 以下のような少し大きめのデータと関数を用意して、それぞれ実行時間、演算後のオブジェクト識別子、バイトコードを確認してみた。
- 関数の呼び出しの前後で
time.time()
を呼び出して差分で実行時間を計測
- 演算後のオブジェクト識別子は、組み込み関数の
id()
を利用
- バイトコードの確認は、
dis
モジュールを利用
def add(list_x, list_y):
list_x = list_x + list_y
return list_x
def inplace(list_x, list_y):
list_x += list_y
return list_x
list_a = [[0 for x in range(10000)] for y in range(10000)]
list_b = [[0 for x in range(10000)] for y in range(10000)]
実験結果
add(list_a, list_b)
実行時間: 0.000458
id(list_a): 4391953400 -> 5530614960
------ dis.dis(add) ------
8 0 LOAD_FAST 0 (list_a)
3 LOAD_FAST 1 (list_b)
6 BINARY_ADD
7 STORE_FAST 0 (list_a)
9 10 LOAD_FAST 0 (list_a)
13 RETURN_VALUE
inplace(list_a, list_b)
実行時間: 0.000285
id(list_a): 5530614960 -> 5530614960
------ dis.dis(inplace) ------
44 0 LOAD_FAST 0 (list_a)
3 LOAD_FAST 1 (list_b)
6 INPLACE_ADD
7 STORE_FAST 0 (list_a)
45 10 LOAD_FAST 0 (list_a)
13 RETURN_VALUE
|
add |
inplace |
結果 |
実行時間 |
0.000458 |
0.000285 |
inplaceの方が早い |
バイトコードの差 |
BINARY_ADD |
INPLACE_ADD |
バイトコードでも変化していることが確認できる |
id(list_a) |
変化あり |
変化なし |
addは新しいオブジェクトとして生成されていて、inplaceは同じオブジェクトに値が代入されている。 |
- どうやらaddの方は新しいオブジェクトのためのメモリ領域を確保しなければならない分、遅くなっているようだ。
- 差は微々たるものだが、内部の動作を意識すると メモリ・実行速度の観点で A+=B を利用したほうが良さそうだと思った。
モチベーション
両者の内部的な動きを意識したことがなかったので自分なりに調査してみた。
「どっちでも一緒やろ!」と思っていた自分が恥ずかしい限り・・・こういった部分まで理解していく姿勢を身につけねばと思い始めた今日この頃です。