Pythonでメモリ消費量のプロファイルを取る

昨日Pythonでメモリを食い過ぎた時に見直すポイントを書いたが、使ったツールの説明を忘れていた。
Guppy-PE: A Python Programming Environmentを使うとこんな感じの出力が得られる。

Partition of a set of 2330379 objects. Total size = 355901024 bytes. 
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class) 
     0 447287  19 125240360  35 125240360  35 dict of __main__.Node 
     1  53016   2 85891008  24 211131368  59 dict (no owner) 
     2 467204  20 66360776  19 277492144  78 str 
     3 457120  20 33019584   9 310511728  87 tuple 
     4 447287  19 28626368   8 339138096  95 __main__.Node 
     5 447381  19 10737144   3 349875240  98 int 
     6    242   0  3714512   1 353589752  99 list 
     7    115   0   360904   0 353950656  99 dict of module 
     8   2719   0   348032   0 354298688 100 types.CodeType 
     9   2629   0   315480   0 354614168 100 function

わかりやすいように短いスクリプトで試してみよう。

from guppy import hpy
h = hpy()
N = 100000

class Hoge(object):
    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インスタンスあたり64バイト、それが持っている辞書が1048バイトなのがわかる。

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
     5    321   0   242328   0 113770736  99 dict (no owner)
     6     68   0   213344   0 113984080  99 dict of module
     7    200   0   211136   0 114195216  99 dict of type
     8   1632   1   208896   0 114404112  99 types.CodeType
     9   1594   1   191280   0 114595392  99 function
<92 more rows. Type e.g. '_.more' to view.>