今回は、iXce’s blog » Blog Archive » Optimizing memory usage in Python: a case study という記事を見つけて興味深かったので紹介したいと思います。何も説明書いてないところがあるので、詳しく知りたい人は元記事を読んでほしいです。
動機
- プレーンテキストをGコードに変換するプログラムを書いている
- 3.8MB (14万Gコード) のファイルを読み込むと、244MBもメモリを使ってしまう
- だからメモリ使用量を減らしたい
やったこと
プロファイル
どこがメモリをたくさん使ってるのか調べるためにHeapyを使う
$ pip install guppy
で入れられる。
するとこんな感じの結果が出力される。
Partition of a set of 225737 objects. Total size = 115386656 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 100000 44 104800000 91 104800000 91 dict of __main__.Hoge
1 100000 44 6400000 6 111200000 96 __main__.Hoge
2 11648 5 1013232 1 112213232 97 str
3 177 0 844360 1 113057592 98 list
4 5849 3 470816 0 113528408 98 tuple
参考: Pythonでメモリ消費量のプロファイルを取る - 西尾泰和のはてなダイアリー
一時データをdel
で消す
del temporary_data
こんな感じ
The __slots__ magic
自作クラスの __slots__ に使うattributeを書く
__slots__ = ('x', 'y', 'z')
こんな感じ
tupleのlistをarrayに置き換える
num = ([1, 2], [1, 1], [2, 1])
みたいのをやめて、こうする
x = array('I', [1, 1, 2])
y = array('I', [2, 1, 1])
def num(idx):
return (x[idx], y[idx])
減らす余地のあるtupleを削除
Cython使ってみる
cyclic garbage collectorを捨てる
CythonコードもHeapyで調べる
結果
メモリ使用量が 244MB から 19.4MBになった!