Pythonで__slots__を使ってメモリを節約
先日こんな実験をして、大量のオブジェクトを作った時にはそのオブジェクトが持っている__dict__の1048バイトが無視できなくなってくることを確認した: Pythonでメモリ消費量のプロファイルを取る
今日はその解決編。先日のコードに1行書き足してみよう。__slots__で始まる行がそれだ。
from guppy import hpy h = hpy() N = 100000 class Hoge(object): __slots__ = ['x', 'y', 'z', 'a', 'b', 'c'] def __init__(self): self.x = 1 self.y = 1 self.z = 1 self.a = 1 self.b = 1 self.c = 1 x = [Hoge() for x in range(N)] print h.heap()
これによって、変更前ではHogeの1インスタンスあたり1048 + 64 = 1112バイトを使っていたが変更後では96バイトしか使わなくなる。
変更前 $ time python tmp.py 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 (...) python tmp.py 3.90s user 0.23s system 89% cpu 4.596 total
変更後 $ time python tmp.py Partition of a set of 125743 objects. Total size = 13788280 bytes. Index Count % Size % Cumulative % Kind (class / dict of class) 0 100000 80 9600000 70 9600000 70 __main__.Hoge (...) python tmp.py 1.51s user 0.07s system 90% cpu 1.747 total
この1行の追加で実行時間が半分以下に減っているのも興味深い。つまり実行時間の結構な部分をメモリの確保で使っていたということだ。
__slots__が何をするものかはこちらを参照: http://www.python.jp/doc/release/reference/datamodel.html#slots