down the rabbit hole, profiling in django

36
Down the rabbit hole Know your code Profiling python

Upload: remco-wendt

Post on 07-May-2015

5.354 views

Category:

Technology


1 download

DESCRIPTION

Presentation given at the Dutch Django Meetup of 19-04-2012

TRANSCRIPT

Page 1: Down the rabbit hole, profiling in Django

Down the rabbit hole

Know your code

Profiling python

Page 2: Down the rabbit hole, profiling in Django

Get those hands dirty

Page 3: Down the rabbit hole, profiling in Django

So……

Page 4: Down the rabbit hole, profiling in Django

The car engine analogy

Page 5: Down the rabbit hole, profiling in Django

Python in that analogy

Page 6: Down the rabbit hole, profiling in Django

Scaling

Page 7: Down the rabbit hole, profiling in Django

Doing a lot of slow thing at the same time

On scaling time.sleep()

Page 8: Down the rabbit hole, profiling in Django

Profiling

Page 9: Down the rabbit hole, profiling in Django

An act of balancing

Page 10: Down the rabbit hole, profiling in Django

Types of profiling

• (code) profiling (cpu/IO bound problems)• memory profiling (obviously memory related

problems)

Page 11: Down the rabbit hole, profiling in Django

(Code) profiling

Page 12: Down the rabbit hole, profiling in Django

Tools

• cProfile• profile• hotshot (deprecated? it splits analysis)• line profiler• trace

Page 13: Down the rabbit hole, profiling in Django

Getting dirty

import cProfilecProfile.run('foo()')

Or

python -m cProfile myscript.py

Page 14: Down the rabbit hole, profiling in Django

More interactive

python -m cProfile myscript.py –o foo.profile

import pstatsp = pstats.Stats('foo.profile')

p.sort_stats('cumulative').print_stats(10)

Page 15: Down the rabbit hole, profiling in Django

More compleximport profile

def fib(n): # from http://en.literateprograms.org/Fibonacci_numbers_(Python) if n == 0: return 0 elif n == 1: return 1 else: return fib(n-1) + fib(n-2)

def fib_seq(n): seq = [ ] if n > 0: seq.extend(fib_seq(n-1)) seq.append(fib(n)) return seq

print 'RAW'print '=' * 80profile.run('print fib_seq(20); print')

Source: http://www.doughellmann.com/PyMOTW/profile/

Page 16: Down the rabbit hole, profiling in Django

Output$ python profile_fibonacci_raw.pyRAW================================================================================[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]

57356 function calls (66 primitive calls) in 0.746 CPU seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function) 21 0.000 0.000 0.000 0.000 :0(append) 20 0.000 0.000 0.000 0.000 :0(extend) 1 0.001 0.001 0.001 0.001 :0(setprofile) 1 0.000 0.000 0.744 0.744 <string>:1(<module>) 1 0.000 0.000 0.746 0.746 profile:0(print fib_seq(20); print) 0 0.000 0.000 profile:0(profiler) 57291/21 0.743 0.000 0.743 0.035 profile_fibonacci_raw.py:13(fib) 21/1 0.001 0.000 0.744 0.744 profile_fibonacci_raw.py:22

Page 17: Down the rabbit hole, profiling in Django

Output$ python profile_fibonacci_raw.pyRAW================================================================================[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]

57356 function calls (66 primitive calls) in 0.746 CPU seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function) 21 0.000 0.000 0.000 0.000 :0(append) 20 0.000 0.000 0.000 0.000 :0(extend) 1 0.001 0.001 0.001 0.001 :0(setprofile) 1 0.000 0.000 0.744 0.744 <string>:1(<module>) 1 0.000 0.000 0.746 0.746 profile:0(print fib_seq(20); print) 0 0.000 0.000 profile:0(profiler) 57291/21 0.743 0.000 0.743 0.035 profile_fibonacci_raw.py:13(fib) 21/1 0.001 0.000 0.744 0.744 profile_fibonacci_raw.py:22

Page 18: Down the rabbit hole, profiling in Django

Memoize!

@memoizedef fib(n):if n == 0: return 0 elif n == 1: return 1 else: return fib(n-1) + fib(n-2)

Page 19: Down the rabbit hole, profiling in Django

Yeah!$ python profile_fibonacci_memoized.pyMEMOIZED================================================================================[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]

145 function calls (87 primitive calls) in 0.003 CPU seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function) 21 0.000 0.000 0.000 0.000 :0(append) 20 0.000 0.000 0.000 0.000 :0(extend) 1 0.001 0.001 0.001 0.001 :0(setprofile) 1 0.000 0.000 0.002 0.002 <string>:1(<module>) 1 0.000 0.000 0.003 0.003 profile:0(print fib_seq(20); print) 0 0.000 0.000 profile:0(profiler) 59/21 0.001 0.000 0.001 0.000 profile_fibonacci.py:19(__call__) 21 0.000 0.000 0.001 0.000 profile_fibonacci.py:26(fib) 21/1 0.001 0.000 0.002 0.002 profile_fibonacci.py:36(fib_seq)

Page 20: Down the rabbit hole, profiling in Django

Line profiling

Line # Hits Time Per Hit % Time Line Contents============================================================== 149 @profile 150 def Proc2(IntParIO): 151 50000 82003 1.6 13.5 IntLoc = IntParIO + 10 152 50000 63162 1.3 10.4 while 1: 153 50000 69065 1.4 11.4 if Char1Glob == 'A': 154 50000 66354 1.3 10.9 IntLoc = IntLoc - 1 155 50000 67263 1.3 11.1 IntParIO = IntLoc - IntGlob 156 50000 65494 1.3 10.8 EnumLoc = Ident1 157 50000 68001 1.4 11.2 if EnumLoc == Ident1: 158 50000 63739 1.3 10.5 break 159 50000 61575 1.2 10.1 return IntParIO

Source: http://packages.python.org/line_profiler/

Page 21: Down the rabbit hole, profiling in Django

More complex == visualize

RunSnakeRun

Page 22: Down the rabbit hole, profiling in Django

Kcachegrind

Pyprof2

calltree

Page 23: Down the rabbit hole, profiling in Django

What to look for?

• Things you didn’t expect ;)• much time spend in one function• lots of calls to same function

Page 24: Down the rabbit hole, profiling in Django

Performance solutions

• caching• getting stuff out of inner loops• removing logging

Page 25: Down the rabbit hole, profiling in Django

Memory profiling

Django has a memory leak

In debug mode ;)

Page 26: Down the rabbit hole, profiling in Django

Tools

• heapy (and pysizer)• meliea (more like hotshot)

Page 27: Down the rabbit hole, profiling in Django

Meliea!

• Memory issues happen sometimes in production (long living processes). Want to get info, then analyze locally

• runsnakerun has support for it

Page 28: Down the rabbit hole, profiling in Django

Dumping

from meliae import scannerscanner.dump_all_objects('filename.json')

Source: http://jam-bazaar.blogspot.com/2009/11/memory-debugging-with-meliae.html

Page 29: Down the rabbit hole, profiling in Django

Analyzing>>> from meliae import loader>>> om = loader.load('filename.json')>>> s = om.summarize(); s

This dumps out something like:Total 17916 objects, 96 types, Total size = 1.5MiB (1539583 bytes)Index Count % Size % Cum Max Kind 0 701 3 546460 35 35 49292 dict 1 7138 39 414639 26 62 4858 str 2 208 1 94016 6 68 452 type 3 1371 7 93228 6 74 68 code 4 1431 7 85860 5 80 60 function 5 1448 8 59808 3 84 280 tuple 6 552 3 40760 2 86 684 list 7 56 0 29152 1 88 596 StgDict 8 2167 12 26004 1 90 12 int 9 619 3 24760 1 91 40 wrapper_descriptor 10 570 3 20520 1 93 36 builtin_function_or_method ...

Page 30: Down the rabbit hole, profiling in Django

Run s n a k e run

Page 31: Down the rabbit hole, profiling in Django

Your production system

A completely different story

Page 32: Down the rabbit hole, profiling in Django

What can you do to prevent this?

• From an API perspective:– Maybe one WSGI process that is different– Gets a small amount of requests (load balancing) – This process takes care of doing profiling

(preferably in the hotshot way)

Page 33: Down the rabbit hole, profiling in Django

Or…..

• Pycounters

• Author is in tha house: Boaz Leskes

Page 34: Down the rabbit hole, profiling in Django

Finally

• You should know about this• Part of your professional toolkit

• This should be in IDE’s!– Komodo already has it, what about PyCharm??

(can you blog this Reinout? ;)

Page 35: Down the rabbit hole, profiling in Django

Questions?

Page 36: Down the rabbit hole, profiling in Django

LinksArticles:http://www.doughellmann.com/PyMOTW/profile/http://www.doughellmann.com/PyMOTW/trace/http://jam-bazaar.blogspot.com/2010/08/step-by-step- meliae.htmlhttps://code.djangoproject.com/wiki/ProfilingDjango

Videos:http://www.youtube.com/watch?v=Iw9-GckD-gQhttp://blip.tv/pycon-us-videos-2009-2010-2011/introduction-to-python-profiling- 1966784

Software:http://www.vrplumber.com/programming/runsnakerun /http://kcachegrind.sourceforge.net/html/Home.htmlhttp://pypi.python.org/pypi/pyprof2calltree/https://launchpad.net/meliaehttp://pypi.python.org/pypi/line_profilerhttp://pypi.python.org/pypi/Dozer