Feb 2, 2012

Django / Python memory profiling

Exapmple:
from accounts.models import UserProfile
p = UserProfile.objects.get(pk=1)
sys
import sys
sys.getsizeof(p)
# 64
sys.getrefcount(p)
# 2
gc
import gc
gc.get_referrers(p)
# [{'Branding': accounts.models.Branding ....
gc.get_objects()
# ...... many objects here
meliae
Unfortunately doesn't work in IPython
./manage.py shell --plain
from meliae import scanner
scanner.get_recursive_size(p)
# (223346, 160192339)
scanner.dump_all_objects('dump.json')
from meliae import loader
om = loader.load('dump.json')
# loaded line 188222, 188223 objs,  22.0 /  22.0 MiB read in 17.7s        
# checked   188222 /   188223 collapsed     5331    
# set parents   182895 /   182896            
# collapsed in 1.7s
om.summarize()
#Total 182896 objects, 810 types, Total size = 31.2MiB (32687019 bytes)
# Index   Count   %      Size   % Cum     Max Kind
#     0    7986   4  11340336  34  34 3146008 dict
#     1   50557  27   4265768  13  47    4648 tuple
#     2   51518  28   4236069  12  60   15347 str
#     3    2358   1   2131632   6  67     904 type
#     4     784   0   1782256   5  72   12624 module
#     5   12163   6   1459560   4  77     120 function
#     6   11453   6   1374360   4  81     120 code
#     7    5356   2   1026560   3  84    4856 list
#     8    2990   1    505996   1  86   23616 unicode
#     9     118   0    403088   1  87    3416 Options
#    10    7548   4    362304   1  88      48 datetime.datetime
#    11   11133   6    267192   0  89      24 int
#    12    2732   1    240416   0  89      88 weakref
#    13     696   0    239424   0  90     344 __proxy__
#    14     161   0    179032   0  91    1112 RelatedObject
#    15     140   0    149536   0  91    1112 ManyToOneRel
#    16     234   0    138376   0  92    3368 SortedDict
#    17    1461   0    116880   0  92      80 wrapper_descriptor
#    18     102   0    113424   0  92    1112 Distribution
#    19     119   0    107576   0  93     904 ModelBase
pip install SquareMap RunSnakeRun
runsnakemem dump.json  # !!! really long operation (wait 2-5min)

heapy
from guppy import hpy
hp = hpy()
h = hp.heap()
h
#Partition of a set of 234126 objects. Total size = 34667856 bytes.
# Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
#     0  90538  39  8491768  24   8491768  24 str
#     1  55160  24  4627144  13  13118912  38 tuple
#     2   3399   1  3018792   9  16137704  47 dict (no owner)
#     3   2267   1  2044536   6  18182240  52 type
#     4    807   0  1779624   5  19961864  58 dict of module
#     5  13148   6  1577760   5  21539624  62 function
#     6   2267   1  1512968   4  23052592  66 dict of type
#     7  12500   5  1500000   4  24552592  71 types.CodeType
#     8   5043   2  1061080   3  25613672  74 list
#     9    240   0   776832   2  26390504  76 dict of 0x18b9fd0
#<1478 more rows. Type e.g. '_.more' to view.>
h.get_rp(40)
#Reference Pattern by <[dict of] class>.
# 0: _ --- [-] 234126 (0x15262c0 | 0x1738820 | 0x1739860 | 0x173b230 | 0x173d1...
# 1: a      [-] 55170 tuple: 0x1024970*45, 0x104a480*28, 0x104a7d0*27...
# 2: aa ---- [S] 2267 type: class..., types.InstanceType, types.MethodType
# 3: ab      [S] 12500 types.CodeType: functional.py:187:__promise__...
# 4: ac ---- [S] 142 dict of module: ..management..., django, sys, types
# 5: ad      [-] 3676 function: urllib.quote..., urllib.splitnport
# 6: ada ---- [S] 324 dict of module: __main__, copy_reg, linecache, os...
# 7: adb      [S] 453 dict of type: ..WarningMessage, ..catch_warnings...
# 8: adc ---- [S] 201 dict of class: ..DictMixin, ..UserDict..., .._Environ
# 9: add      [-] 67 dict of django.db.models.base.ModelBase: 0x19c6370...
#
Pympler
Identifying memory leaks

The refbrowser module


objgraph
apt-get install graphviz graphviz-dev
pip install objgraph
import objgraph
objgraph.show_refs([p], filename='sample-graph.png')
objgraph.show_most_common_types()
objgraph.show_growth()
objgraph.show_backref([x], filename="/tmp/backrefs.png")
Linux
http://www.linuxatemyram.com/
free -m
ps aux --sort -rss
cat /proc/PID/status
pmap -x PID
Django
geordi - A Django middleware for interactive profiling

From:
http://blip.tv/pycon-us-videos-2009-2010-2011/pycon-2011-dude-where-s-my-ram-a-deep-dive-into-how-python-uses-memory-4896725
http://python.mirocommunity.org/video/1759/pyconau-2010-whats-eating-my-m 
http://jam-bazaar.blogspot.com/2009/11/memory-debugging-with-meliae.html

See also
https://fedorahosted.org/pulp/wiki/Debugging/MemoryLeaks 

http://stackoverflow.com/questions/110259/which-python-memory-profiler-is-recommended