Search for memory leaks in a tornado project
Guppy doesn't work with Python 3 (for February 2015).
requirements.txt:
guppy
Use MemoryHandler to inspect memory usage:
from guppy import hpy from tornado import web, ioloop, gen, options class LeakObject(object): def __init__(self): self.a = {} for i in xrange(1000): self.a[i] = 'leak' * 1000 def __del__(self): pass class LeakHandler(web.RequestHandler): def get(self): # create memory leak obj1 = LeakObject() obj2 = LeakObject() obj1.leak = obj2 obj2.leak = obj1 self.write('Leak') class MemoryHandler(web.RequestHandler): def get(self): h = hpy() r = h.heap() self.write('<pre>') self.write(unicode(r)) r = r.more self.write(unicode(r)) r = r.more self.write(unicode(r)) self.write('</pre>') application = web.Application([ (r'/leak', LeakHandler), (r'/memory', MemoryHandler), ], debug=True) if __name__ == "__main__": options.parse_command_line() application.listen(5000) ioloop.IOLoop.instance().start()
nanvel-air:leaks nanvel$ curl http://localhost:5000/leak Leak ... nanvel-air:leaks nanvel$ curl http://localhost:5000/memory <pre> Partition of a set of 153822 objects. Total size = 206002744 bytes. Index Count % Size % Cumulative % Kind (class / dict of class) 0 83492 54 197180696 96 197180696 96 str 1 341 0 2958200 1 200138896 97 dict (no owner) 2 15243 10 1287768 1 201426664 98 tuple 3 37662 24 903888 0 202330552 98 int 4 202 0 652528 0 202983080 99 dict of module 5 4172 3 534016 0 203517096 99 types.CodeType 6 3994 3 479280 0 203996376 99 function 7 493 0 457528 0 204453904 99 dict of type 8 493 0 442384 0 204896288 99 type 9 201 0 199128 0 205095416 100 dict of class <188 more rows. Type e.g. '_.more' to view.> Index Count % Size % Cumulative % Kind (class / dict of class) 10 426 0 100816 0 205196232 100 list 11 1187 1 94960 0 205291192 100 __builtin__.wrapper_descriptor 12 844 1 74272 0 205365464 100 __builtin__.weakref 13 885 1 63720 0 205429184 100 types.BuiltinFunctionType 14 698 0 50256 0 205479440 100 __builtin__.method_descriptor 15 178 0 41296 0 205520736 100 __builtin__.set 16 19 0 40648 0 205561384 100 dict of email.LazyImporter 17 585 0 34808 0 205596192 100 unicode 18 26 0 31856 0 205628048 100 dict of abc.ABCMeta 19 68 0 30024 0 205658072 100 _sre.SRE_Pattern <178 more rows. Type e.g. '_.more' to view.> Index Count % Size % Cumulative % Kind (class / dict of class) 20 96 0 26880 0 205684952 100 dict of function 21 355 0 25560 0 205710512 100 types.GetSetDescriptorType 22 26 0 23504 0 205734016 100 abc.ABCMeta 23 78 0 21840 0 205755856 100 dict of _weakrefset.WeakSet 24 201 0 20904 0 205776760 100 class 25 255 0 18360 0 205795120 100 types.MemberDescriptorType > 26 48 0 13440 0 205808560 100 dict of __main__.LeakObject 27 138 0 12144 0 205820704 100 __builtin__.property 28 22 0 11536 0 205832240 100 dict of guppy.etc.Glue.Interface 29 202 0 11312 0 205843552 100 module <168 more rows. Type e.g. '_.more' to view.></pre>
UPD: 2017-06-29
Another tool: memory_profiler. Supports Python3.
Licensed under CC BY-SA 3.0