SlideShare une entreprise Scribd logo
1  sur  131
Télécharger pour lire hors ligne
Профилирование и отладка
Django
Владимир Рудных
Moscow Django MeetUp №13
Обо мне
• технический руководитель
Календаря Mail.Ru
• pythonista
• бывший перловик
• ленивый программист
Moscow Django MeetUp №13
Cбор характеристик работы программы
с целью их дальнейшей оптимизации.
Профилирование
Moscow Django MeetUp №13
Что собираем?
• время выполнения строк кода
• количество вызовов функций
• время выполнения функций
• дерево вызовов функций
• “hot spots”
• загрузку CPU, использование памяти
• и т.д.
Moscow Django MeetUp №13
Project Euler
http://projecteuler.net
Тренируемся
Moscow Django MeetUp №13
Простые делители числа 13195 — это 5, 7, 13 и 29.
Какой самый большой делитель числа 600851475143,
являющийся простым числом?
Project Euler: задача 3
Moscow Django MeetUp №13
1 """Project Euler problem 3 solve"""
2
3
4 def is_prime(num):
5 """Checks if num is prime number"""
6 for i in range(2, num):
7 if not num % i:
8 return False
9 return True
10
11
12 def prime_factors(num):
13 """Find prime factors of num"""
14 result = []
15 for i in range(2, num):
16 if is_prime(i) and not num % i:
17 result.append(i)
18 return result
19
20
21 if __name__ == '__main__':
22 print "Answer: %d" % prime_factors(600851475143)[-1]
Project Euler: задача 3
Moscow Django MeetUp №13
Moscow Django MeetUp №13
Moscow Django MeetUp №13
Профилирование начинается в голове.
Инструменты — всего лишь инструменты.
Искусство профилирования
Moscow Django MeetUp №13
1 """Project Euler problem 3 solve"""
2 from math import sqrt
3
4
5 def is_prime(num):
6 """Checks if num is prime number"""
7 for i in range(2, int(sqrt(num)) + 1):
8 if not num % i:
9 return False
10 return True
11
12
13 def prime_factors(num):
14 """Find prime factors of num"""
15 result = []
16 for i in range(2, int(sqrt(num)) + 1):
17 if is_prime(i) and not num % i:
18 result.append(i)
19 return result
20
21
22 if __name__ == '__main__':
23 print "Answer: %d" % prime_factors(600851475143)[-1]
Project Euler: задача 3
Moscow Django MeetUp №13
Подходы к профилированию
• ручное профилирование
• с помощью инструментов
Moscow Django MeetUp №13
Ручное профилирование
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ time python max_prime_factor.py
Answer: 6857
python max_prime_factor.py 20,00s user 0,19s system 82% cpu 24,445 total
Ручное профилирование
Moscow Django MeetUp №13
1 """Project Euler problem 3 solve"""
2 import time
3 from math import sqrt
4
5
6 def is_prime(num):
7 """Checks if num is prime number"""
8 for i in range(2, int(sqrt(num)) + 1):
9 if not num % i:
10 return False
11 return True
12
13
14 def prime_factors(num):
15 """Find prime factors of num"""
16 result = []
17 for i in range(2, int(sqrt(num)) + 1):
18 if is_prime(i) and not num % i:
19 result.append(i)
20 return result
21
22
23 if __name__ == '__main__':
24 start = time.time()
25 print "Answer: %d" % prime_factors(600851475143)[-1]
26 print "Time: %f s" % (time.time() - start)
Ручное профилирование
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python max_prime_factor.py
Answer: 6857
Time: 23.531779 s
Ручное профилирование
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python max_prime_factor.py
Answer: 6857
Time: 21.143574 s
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python max_prime_factor.py
Answer: 6857
Time: 22.638407 s
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python max_prime_factor.py
Answer: 6857
Time: 20.774542 s
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python max_prime_factor.py
Answer: 6857
Time: 22.272329 s
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python max_prime_factor.py
Answer: 6857
Time: 23.562760 s
Ручное профилирование
Moscow Django MeetUp №13
timeit
http://docs.python.org/2/library/timeit.html
Ручное профилирование
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python -m timeit -n 10 -s'from max_prime_factor import prime_factors' 'prime_factors(600851475143)'
10 loops, best of 3: 22.3 sec per loop
timeit
Moscow Django MeetUp №13
Ручное профилирование
очень простое применение
ограниченно подходит
для продакшена
вставка чужеродного кода в проект
никакой информации о коде
(кроме времени выполнения)
анализ результатов может быть
затруднительным
Moscow Django MeetUp №13
— Зацени, мой код быстрее твоего!
Применение
Moscow Django MeetUp №13
Применение
Moscow Django MeetUp №13
Сбор статистики времени выполнения кода.
Например, в graphite или statsd:
Применение в реальной жизни
Moscow Django MeetUp №13
1 """Collect profiling statistic into graphite"""
2 import socket
3 import time
4
5
6 CARBON_SERVER = '127.0.0.1'
7 CARBON_PORT = 2003
8
9
10 class Stats(object):
11 """Context manager for send stats to graphite"""
12
13 def __init__(self, name):
14 self.name = name
15
16 def __enter__(self):
17 self.start = time.time()
18 return self
19
20 def __exit__(self, *args):
21 duration = (time.time() - self.start) * 1000 # msec
22 message = '%s %d %dn' % (self.name, duration, time.time())
23
24 sock = socket.socket()
25 sock.connect((CARBON_SERVER, CARBON_PORT))
26 sock.sendall(message)
27 sock.close()
Менеджер контекста
Moscow Django MeetUp №13
from django.core.mail import send_mail
from profiling.context_managers import Stats
...
with Stats('django_project.profiling.send_email'):
send_mail(
'Subject here',
'Here is the message.',
'from@example.com',
['to@example.com'],
fail_silently=False
)
Пример использования
Moscow Django MeetUp №13
1 """Collect profiling statistic into graphite"""
2 import socket
3 import time
4
5
6 CARBON_SERVER = '127.0.0.1'
7 CARBON_PORT = 2003
8
9
10 def stats(name):
11 """Decorator for send stats to graphite"""
12 def _timing(func):
13 def _wrapper(*args, **kwargs):
14 start = time.time()
15 result = func(*args, **kwargs)
16 duration = (time.time() - start) * 1000 # msec
17 message = '%s %d %dn' % (name, duration, time.time())
18
19 sock = socket.socket()
20 sock.connect((CARBON_SERVER, CARBON_PORT))
21 sock.sendall(message)
22 sock.close()
23
24 return result
25 return _wrapper
26 return _timing
Декоратор
Moscow Django MeetUp №13
from django.db import models
from profiling.decorator import stats
...
class Model(model.Model):
...
@stats('django_project.profiling.application.save')
def save(self, *args, **kwargs):
# do some hard work like thumbnail generation
super(Model, self).save(*args, **kwargs)
Пример использования
Moscow Django MeetUp №13
Статистика профилирования
Moscow Django MeetUp №13
Профилирование
с помощью инструментов
Moscow Django MeetUp №13
Инструменты для профилирования
•Deterministic (event-based)
•Statistical
Moscow Django MeetUp №13
def is_prime(num):
"""Checks if num is prime number"""
for i in range(2, num):
if not num % i:
return False
return True
Deterministic profilers
@profile
def is_prime(num):
"""Checks if num is prime number"""
for i in range(2, num):
if not num % i:
return False
return True
Moscow Django MeetUp №13
def is_prime(num):
"""Checks if num is prime number"""
with profile():
for i in range(2, num):
if not num % i:
return False
return True
Deterministic profilers
def is_prime(num):
"""Checks if num is prime number"""
profile.start()
for i in range(2, num):
if not num % i:
return False
profile.stop()
return True
Moscow Django MeetUp №13
Deterministic profilers
def foo()
def bar()
def baz() def ololo()
Moscow Django MeetUp №13
Deterministic profilers
вся информация о коде
множество инструментов для анализа
очень медленно
непригодно для продакшена
(или крайне ограниченно)
Moscow Django MeetUp №13
Statistical profilers
def foo() def bar() def baz()
def foo() def bar() def baz()
Timer: 1ms
Timer: 10ms
Moscow Django MeetUp №13
Statistical profilers
def foo() def foo() def foo() def foo()def foo()
def foo()
Moscow Django MeetUp №13
Statistical profilers
можно пускать в продакшн
(практически не влияет на быстродействие)
не вся информация о коде
мало инструментов для анализа
Moscow Django MeetUp №13
Deterministic profilers
• profile
• cProfile
• hotshot
• kcachegrind
• RunSnakeRun
• gprof2dot
• pycallgraph
• line_profiler
• memory_profiler
• dowser
• guppy
• muppy
• memprof
• objgraph
“тысячи их”...
Moscow Django MeetUp №13
cProfile
http://docs.python.org/2/library/profile.html
Инструменты для профилирования
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python -m cProfile -s time max_prime_factor.py
Answer: 6857
2325444 function calls in 21.912 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
775145 14.240 0.000 21.233 0.000 max_prime_factor.py:5(is_prime)
775146 6.779 0.000 6.779 0.000 {range}
1 0.630 0.630 21.909 21.909 max_prime_factor.py:13(prime_factors)
775146 0.260 0.000 0.260 0.000 {math.sqrt}
1 0.003 0.003 21.912 21.912 max_prime_factor.py:1(<module>)
4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
cProfile
Moscow Django MeetUp №13
1 """Project Euler problem 3 solve"""
2 from math import sqrt
3
4
5 def is_prime(num):
6 """Checks if num is prime number"""
7 for i in range(2, int(sqrt(num)) + 1):
8 if not num % i:
9 return False
10 return True
11
12
13 def prime_factors(num):
14 """Find prime factors of num"""
15 result = []
16 for i in range(2, int(sqrt(num)) + 1):
17 if is_prime(i) and not num % i:
18 result.append(i)
19 return result
20
21
22 if __name__ == '__main__':
23 print "Answer: %d" % prime_factors(600851475143)[-1]
Project Euler: задача 3
Moscow Django MeetUp №13
1 """Project Euler problem 3 solve"""
2 from math import sqrt
3
4
5 def is_prime(num):
6 """Checks if num is prime number"""
7 for i in range(2, int(sqrt(num)) + 1):
8 if not num % i:
9 return False
10 return True
11
12
13 def prime_factors(num):
14 """Find prime factors of num"""
15 result = []
16 for i in range(2, int(sqrt(num)) + 1):
17 if not num % i and is_prime(i):
18 result.append(i)
19 return result
20
21
22 if __name__ == '__main__':
23 print "Answer: %d" % prime_factors(600851475143)[-1]
Project Euler: задача 3
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python -m cProfile -s time max_prime_factor.py
Answer: 6857
30 function calls in 0.225 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.179 0.179 0.250 0.250 max_prime_factor.py:13(prime_factors)
8 0.070 0.009 0.070 0.009 {range}
1 0.003 0.003 0.253 0.253 max_prime_factor.py:1(<module>)
7 0.000 0.000 0.000 0.000 max_prime_factor.py:5(is_prime)
8 0.000 0.000 0.000 0.000 {math.sqrt}
4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
cProfile
Moscow Django MeetUp №13
Ускорил код в сто раз
Moscow Django MeetUp №13
import cProfile
def profile(func):
"""Decorator for run function profile"""
def wrapper(*args, **kwargs):
profile_filename = func.__name__ + '.profile'
profiler = cProfile.Profile()
result = profiler.runcall(func, *args, **kwargs)
profiler.dump_stats(profile_filename)
return result
return wrapper
@profile
def foo():
...
cProfile: декоратор
Moscow Django MeetUp №13
hotshot
http://docs.python.org/2/library/hotshot.html
Инструменты для профилирования
Moscow Django MeetUp №13
import hotshot
prof = hotshot.Profile("profile_name.prof")
prof.start()
# your code goes here
prof.stop()
prof.close()
hotshot: использование
Moscow Django MeetUp №13
import hotshot
def profile(func):
"""Decorator for run function profile"""
def wrapper(*args, **kwargs):
profile_filename = func.__name__ + '.profile'
profiler = hotshot.Profile(profile_filename)
profiler.start()
result = func(*args, **kwargs)
profiler.stop()
profiler.close()
return result
return wrapper
@profile
def foo():
...
hotshot: декоратор
Moscow Django MeetUp №13
cProfile, hotshot
мощные инструменты
достаточно простые
дерево вызовов функций
сильно влияют на производительность
анализ результатов может быть
затруднительным
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ time python max_prime_factor.py
Answer: 6857
python max_prime_factor.py 0,18s user 0,01s system 95% cpu 0,199 total
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ time python -m cProfile max_prime_factor.py
Answer: 6857
22 function calls in 0.252 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.005 0.005 0.252 0.252 max_prime_factor.py:1(<module>)
1 0.247 0.247 0.247 0.247 max_prime_factor.py:13(prime_factors)
7 0.000 0.000 0.000 0.000 max_prime_factor.py:5(is_prime)
8 0.000 0.000 0.000 0.000 {math.sqrt}
4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
python -m cProfile max_prime_factor.py 0,23s user 0,09s system 58% cpu 0,541 total
cProfile: производительность
Moscow Django MeetUp №13
Сохраняем результаты профилирования
в файл для дальнейшего анализа:
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python -m cProfile -o max_prime_factor.prof max_prime_factor.py
Answer: 6857
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ ls
max_prime_factor.prof max_prime_factor.py
cProfile: анализ результатов
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ ipython
In [1]: import pstats
In [2]: p = pstats.Stats('max_prime_factor.prof')
In [3]: p.sort_stats('calls')
Out[3]: <pstats.Stats instance at 0x10689bf80>
In [4]: p.print_stats(5)
22 function calls in 0.166 seconds
Ordered by: call count
List reduced from 6 to 5 due to restriction <5>
ncalls tottime percall cumtime percall filename:lineno(function)
8 0.000 0.000 0.000 0.000 {math.sqrt}
7 0.000 0.000 0.000 0.000 max_prime_factor.py:5(is_prime)
4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
1 0.003 0.003 0.166 0.166 max_prime_factor.py:1(<module>)
1 0.163 0.163 0.163 0.163 max_prime_factor.py:13(prime_factors)
Out[4]: <pstats.Stats instance at 0x10689bf80>
Анализ: pstats
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ pip install pyprof2calltree
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ pyprof2calltree -i max_prime_factor.prof -o max_prime_factor.kgrind
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ pyprof2calltree -i max_prime_factor.prof -k
Анализ: kcachegrind
Moscow Django MeetUp №13
Анализ: kcachegrind
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ brew install wxwidgets
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ pip install SquareMap RunSnakeRun
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ runsnake max_prime_factor.prof
Анализ: RunSnakeRun
Moscow Django MeetUp №13
Анализ: RunSnakeRun
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ brew install graphviz
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ pip install gprof2dot
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ gprof2dot -f pstats max_prime_factor.prof | dot -Tpng -o max_prime_factor.png
Анализ: gprof2dot
Moscow Django MeetUp №13
Анализ: gprof2dot
Moscow Django MeetUp №13
Но где же Django?
Moscow Django MeetUp №13
Профилируем Django
• Устанавливаем модуль:
➜ pip install django-extensions
• Добавляем application в Django:
INSTALLED_APPS += ('django_extensions',)
• Запускаем тестовый сервер:
➜ python manage.py runprofileserver 
--use-cprofile 
--prof-path=/tmp/prof/
Moscow Django MeetUp №13
Получаем по одному *.prof файлу на запрос:
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ ls /tmp/prof/
admin.000276ms.1374075009.prof
admin.account.user.000278ms.1374075014.prof
admin.jsi18n.000185ms.1374075018.prof
favicon.ico.000017ms.1374075001.prof
root.000073ms.1374075004.prof
static.admin.css.base.css.000011ms.1374075010.prof
static.admin.css.forms.css.000013ms.1374075017.prof
static.admin.img.icon-yes.gif.000001ms.1374075015.prof
static.admin.img.sorting-icons.gif.000001ms.1374075015.prof
static.admin.js.core.js.000018ms.1374075014.prof
static.admin.js.jquery.js.000003ms.1374075014.prof
static.css.bootstrap-2.3.2.min.css.000061ms.1374074996.prof
static.img.glyphicons-halflings.png.000001ms.1374075005.prof
static.js.bootstrap-2.3.2.min.js.000004ms.1374074996.prof
static.js.jquery-2.0.2.min.js.000001ms.1374074996.prof
user.login.000187ms.1374075001.prof
А дальшё всё как обычно:
Профилируем Django
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ ipython
In [1]: import pstats
In [2]: p = pstats.Stats('/tmp/prof/user.login.000187ms.1374075001.prof')
In [3]: p.sort_stats('calls')
Out[3]: <pstats.Stats instance at 0x107efa5f0>
In [4]: p.print_stats(5)
36854 function calls (35710 primitive calls) in 0.187 seconds
Ordered by: call count
List reduced from 774 to 5 due to restriction <5>
ncalls tottime percall cumtime percall filename:lineno(function)
4714 0.002 0.000 0.002 0.000 {method 'append' of 'list' objects}
3562 0.003 0.000 0.003 0.000 {isinstance}
2456 0.003 0.000 0.003 0.000 {method 'startswith' of 'unicode' objects}
1058/1048 0.002 0.000 0.002 0.000 {getattr}
979/962 0.000 0.000 0.025 0.000 {len}
Out[4]: <pstats.Stats instance at 0x107efa5f0>
Анализ: pstats
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ pyprof2calltree -i /tmp/prof/user.login.000187ms.1374075001.prof -k
Анализ: kcachegrind
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ runsnake /tmp/prof/user.login.000187ms.1374075001.prof
Анализ: RunSnakeRun
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ gprof2dot -f pstats /tmp/prof/user.login.000187ms.1374075001.prof | dot -Tpng -o login.png
Анализ: gprof2dot
Moscow Django MeetUp №13
Ещё инструменты
Moscow Django MeetUp №13
pycallgraph
http://pycallgraph.slowchop.com/
Инструменты для профилирования
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ pip install pycallgraph
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ pycallgraph max_prime_factor.py
Python Call Graph v0.5.1
Starting trace
Answer: 6857
Creating pycallgraph.png
Done!
pycallgraph
Moscow Django MeetUp №13
import pycallgraph
pycallgraph.start_trace()
# your code goes here
pycallgraph.make_dot_graph('call-graph.png')
pycallgraph
Moscow Django MeetUp №13
line_profiler
https://bitbucket.org/robertkern/line_profiler
Инструменты для профилирования
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ kernprof.py -v -l max_prime_factor.py
Function: is_prime at line 5
Total time: 0.001412 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
6 def is_prime(num):
7 """Checks if num is prime number"""
8 366 767 2.1 54.3 for i in range(2, int(sqrt(num)) + 1):
9 362 614 1.7 43.5 if not num % i:
10 3 23 7.7 1.6 return False
11 4 8 2.0 0.6 return True
Function: prime_factors at line 14
Total time: 2.67703 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
15 def prime_factors(num):
16 """Find prime factors of num"""
17 1 4 4.0 0.0 result = []
18 775146 1320370 1.7 49.3 for i in range(2, int(sqrt(num)) + 1):
19 775145 1356632 1.8 50.7 if not num % i and is_prime(i):
20 4 16 4.0 0.0 result.append(i)
21 1 10 10.0 0.0 return result
line_profiler
Moscow Django MeetUp №13
memory_profiler
https://github.com/fabianp/memory_profiler
Инструменты для профилирования
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python -m memory_profiler max_prime_factor.py
Line # Mem usage Increment Line Contents
================================================
6 def is_prime(num):
7 32.469 MB 0.000 MB """Checks if num is prime number"""
8 57.414 MB 24.945 MB for i in range(2, int(sqrt(num)) + 1):
9 57.414 MB 0.000 MB if not num % i:
10 32.566 MB -24.848 MB return False
11 33.047 MB 0.480 MB return True
Line # Mem usage Increment Line Contents
================================================
15 def prime_factors(num):
16 8.379 MB 0.000 MB """Find prime factors of num"""
17 8.379 MB 0.000 MB result = []
18 75.332 MB 66.953 MB for i in range(2, int(sqrt(num)) + 1):
19 33.047 MB -42.285 MB if not num % i and is_prime(i):
20 75.332 MB 42.285 MB result.append(i)
21 75.332 MB 0.000 MB return result
memory_profiler
Moscow Django MeetUp №13
1 """Project Euler problem 3 solve"""
2 from math import sqrt
3
4
5 def is_prime(num):
6 """Checks if num is prime number"""
7 for i in xrange(2, int(sqrt(num)) + 1):
8 if not num % i:
9 return False
10 return True
11
12
13 def prime_factors(num):
14 """Find prime factors of num"""
15 result = []
16 for i in xrange(2, int(sqrt(num)) + 1):
17 if not num % i and is_prime(i):
18 result.append(i)
19 return result
20
21
22 if __name__ == '__main__':
23 print "Answer: %d" % prime_factors(600851475143)[-1]
Project Euler: задача 3
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python -m memory_profiler max_prime_factor.py
Line # Mem usage Increment Line Contents
================================================
6 def is_prime(num):
7 8.391 MB 0.000 MB """Checks if num is prime number"""
8 22.605 MB 14.215 MB for i in xrange(2, int(sqrt(num)) + 1):
9 22.605 MB 0.000 MB if not num % i:
10 8.484 MB -14.121 MB return False
11 8.965 MB 0.480 MB return True
Line # Mem usage Increment Line Contents
================================================
15 def prime_factors(num):
16 8.379 MB 0.000 MB """Find prime factors of num"""
17 8.379 MB 0.000 MB result = []
18 34.141 MB 25.762 MB for i in xrange(2, int(sqrt(num)) + 1):
19 8.965 MB -25.176 MB if not num % i and is_prime(i):
20 34.141 MB 25.176 MB result.append(i)
21 34.141 MB 0.000 MB return result
memory_profiler
Moscow Django MeetUp №13
И ещё инструменты
Moscow Django MeetUp №13
Профилирование памяти
Dowser
http://www.aminus.net/wiki/Dowser
Инструменты для профилирования
Moscow Django MeetUp №13
Профилирование памяти
guppy
http://guppy-pe.sourceforge.net/
Инструменты для профилирования
Moscow Django MeetUp №13
Обнаружение утечек памяти
muppy
http://pythonhosted.org/Pympler/muppy.html
Инструменты для профилирования
Moscow Django MeetUp №13
Профилирование памяти
memprof
http://jmdana.github.io/memprof/
Инструменты для профилирования
Moscow Django MeetUp №13
Исследование объектов
objgraph
http://mg.pov.lt/objgraph/
Инструменты для профилирования
Moscow Django MeetUp №13
Statistical profilers
• StatProf
• Plop
• New Relic
Moscow Django MeetUp №13
statprof
https://github.com/bos/statprof.py
Инструменты для профилирования
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ pip install statprof
import statprof
statprof.start()
try:
function()
finally:
statprof.stop()
statprof.display()
import statprof
with statprof.profile():
function()
statprof
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ time python max_prime_factor.py
Answer: 6857
python max_prime_factor.py 10,42s user 0,04s system 97% cpu 10,750 total
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ time python max_prime_factor.py
Answer: 6857
% cumulative self
time seconds seconds name
83.03 8.82 8.82 max_prime_factor.py:9:is_prime
13.52 1.44 1.44 max_prime_factor.py:8:is_prime
2.01 10.62 0.21 max_prime_factor.py:18:prime_factors
0.88 0.09 0.09 max_prime_factor.py:6:is_prime
0.48 0.05 0.05 max_prime_factor.py:10:is_prime
0.06 0.01 0.01 max_prime_factor.py:11:is_prime
0.03 10.62 0.00 max_prime_factor.py:26:<module>
---
Sample count: 3535
Total time: 10.620000 seconds
python max_prime_factor.py 10,56s user 0,17s system 90% cpu 11,908 total
statprof
Moscow Django MeetUp №13
statprof
• Устанавливаем zeromq (нужна для работы):
➜ brew install zmq
• Устанавливаем модуль:
➜ pip install statprof django-live-profiler
• Запускаем аггрегатор:
➜ aggregated --host 127.0.0.1 --port 5556
Moscow Django MeetUp №13
statprof
• Добавляем application в Django:
INSTALLED_APPS += ('profiler',)
• Добавляем middleware:
MIDDLEWARE_CLASSES += (
'profiler.middleware.ProfilerMiddleware',
'profiler.middleware.StatProfMiddleware')
• Добавляем urls:
url(r'^profiler/', include('profiler.urls'))
• Запускаем Django:
➜ python manage.py runserver --noreload --nothreading
Moscow Django MeetUp №13
statprof
Moscow Django MeetUp №13
statprof
Moscow Django MeetUp №13
statprof
небольшой оверхед
можно пускать в продакшн
(если осторожно)
профилирование SQL-запросов
сложная установка, зависимости
мало данных на выходе
Moscow Django MeetUp №13
plop
https://github.com/bdarnell/plop
Инструменты для профилирования
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ pip install plop tornado
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python -m plop.collector max_prime_factor.py
Answer: 6857
profile output saved to /tmp/plop.out
overhead was 4.78124272996e-05 per sample (0.00478124272996%)
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python -m plop.viewer --datadir=/tmp/
plop
Moscow Django MeetUp №13
plop
Moscow Django MeetUp №13
plop
Moscow Django MeetUp №13
plop
• Устанавливаем модули:
➜ pip install plop django-plop tornado
• Добавляем application в Django:
INSTALLED_APPS += ('django_plop',)
• Добавляем middleware:
MIDDLEWARE_CLASSES += (
'django_plop.middleware.PlopMiddleware',)
• Указываем путь для сохранения результатов:
PLOP_DIR = os.path.join(ROOT_DIR, 'plop')
Moscow Django MeetUp №13
plop
• Запускаем Django:
➜ python manage.py runserver --noreload --nothreading
• Запускаем просмотр результатов:
➜ python -m plop.viewer --datadir=plop
Moscow Django MeetUp №13
plop
минимальный оверхед (около 2%)
можно пускать в продакшн
сложная установка, зависимости
очень мало данных на выходе
Moscow Django MeetUp №13
New Relic
http://newrelic.com/
Инструменты для профилирования
Moscow Django MeetUp №13
New Relic
Moscow Django MeetUp №13
New Relic
Moscow Django MeetUp №13
New Relic
Moscow Django MeetUp №13
New Relic
предназначен для продакшена
огромный функционал
платный (есть бесплатная версия)
данные отправляются на чужие
серверы
Moscow Django MeetUp №13
Django Debug Toolbar
https://github.com/django-debug-toolbar/django-debug-toolbar
Инструменты для профилирования
Moscow Django MeetUp №13
Django Debug Toolbar
• Устанавливаем модули:
➜ pip install django-debug-toolbar
• Добавляем application в Django:
INSTALLED_APPS += ('debug_toolbar',)
• Добавляем middleware:
MIDDLEWARE_CLASSES += (
'debug_toolbar.middleware.DebugToolbarMiddleware',)
• Указываем IP для которых показываем тулбар:
INTERNAL_IPS = ('127.0.0.1',)
Moscow Django MeetUp №13
Django Debug Toolbar
Moscow Django MeetUp №13
Django Debug Toolbar
Moscow Django MeetUp №13
Django Debug Toolbar
Moscow Django MeetUp №13
Django Debug Toolbar
прост в установке и использовании
огромный функционал
расширяемый (плагины)
не для продакшена (?)
данные никуда не сохраняются
(только просмотр в реальном времени)
Moscow Django MeetUp №13
Django StatsD
https://github.com/andymckay/django-statsd
Инструменты для профилирования
Moscow Django MeetUp №13
Django StatsD
• Устанавливаем модули:
➜ pip install django-statsd-mozilla
• Добавляем application в Django:
INSTALLED_APPS += ('django_statsd',)
• Добавляем middleware:
MIDDLEWARE_CLASSES += (
'django_statsd.middleware.GraphiteRequestTimingMiddleware',
'django_statsd.middleware.GraphiteMiddleware',)
• Указываем, что хотим получать тайминги БД:
STATSD_PATCHES = ['django_statsd.patches.db']
Moscow Django MeetUp №13
Django StatsD
Moscow Django MeetUp №13
Django StatsD
прост в установке и использовании
используется в продакшене
мало информации (количество/время)
Нужен graphite и statsd (must-have)
Moscow Django MeetUp №13
Обнаружение, локализация
и устранение ошибок.
Отладка
Moscow Django MeetUp №13
The Python Debugger
http://docs.python.org/2/library/pdb.html
Инструменты для отладки
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python -m pdb max_prime_factor.py
> /home/rudnyh/work/python-profiling/max_prime_factor.py(1)<module>()
-> """Project Euler problem 3 solve"""
(Pdb) next
> /home/rudnyh/work/python-profiling/max_prime_factor.py(2)<module>()
-> from math import sqrt
(Pdb) next
> /home/rudnyh/work/python-profiling/max_prime_factor.py(5)<module>()
-> def is_prime(num):
(Pdb) next
> /home/rudnyh/work/python-profiling/max_prime_factor.py(13)<module>()
-> def prime_factors(num):
(Pdb) next
> /home/rudnyh/work/python-profiling/max_prime_factor.py(22)<module>()
-> if __name__ == '__main__':
(Pdb) next
> /home/rudnyh/work/python-profiling/max_prime_factor.py(23)<module>()
-> print "Answer: %d" % prime_factors(600851475143)[-1]
(Pdb) next
Answer: 6857
--Return--
> /home/rudnyh/work/python-profiling/max_prime_factor.py(23)<module>()->None
-> print "Answer: %d" % prime_factors(600851475143)[-1]
(Pdb) quit
pdb
Moscow Django MeetUp №13
1 """Project Euler problem 3 solve"""
2 from math import sqrt
3
4
5 def is_prime(num):
6 """Checks if num is prime number"""
7 import pdb; pdb.set_trace()
8 for i in xrange(2, int(sqrt(num)) + 1):
9 if not num % i:
10 return False
11 return True
12
13
14 def prime_factors(num):
15 """Find prime factors of num"""
16 result = []
17 for i in xrange(2, int(sqrt(num)) + 1):
18 if not num % i and is_prime(i):
19 result.append(i)
20 return result
21
22
23 if __name__ == '__main__':
24 print "Answer: %d" % prime_factors(600851475143)[-1]
pdb
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python max_prime_factor.py
> /home/rudnyh/work/python-profiling/max_prime_factor.py(8)is_prime()
-> for i in xrange(2, int(sqrt(num)) + 1):
(Pdb) list
3 	
4 	
5 	 def is_prime(num):
6 	 """Checks if num is prime number"""
7 	 import pdb; pdb.set_trace()
8 ->	 for i in xrange(2, int(sqrt(num)) + 1):
9 	 if not num % i:
10 	 return False
11 	 return True
12 	
13 	
(Pdb) next
> /home/rudnyh/work/python-profiling/max_prime_factor.py(9)is_prime()
-> if not num % i:
(Pdb) continue
> /home/rudnyh/work/python-profiling/max_prime_factor.py(8)is_prime()
-> for i in xrange(2, int(sqrt(num)) + 1):
(Pdb)
pdb
Moscow Django MeetUp №13
pdb
практически неограниченный функционал
не очень удобно
Moscow Django MeetUp №13
django-pdb
https://github.com/tomchristie/django-pdb
Инструменты для отладки
Moscow Django MeetUp №13
django-pdb
• Устанавливаем модули:
➜ pip install django-pdb
• Добавляем application в Django:
INSTALLED_APPS += ('django_pdb',)
• Добавляем middleware:
MIDDLEWARE_CLASSES += ('django_pdb.middleware.PdbMiddleware',)
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python manage.py runserver
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python manage.py runserver --pdb
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python manage.py runserver --ipdb
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ python manage.py runserver --pm
django-pdb
Moscow Django MeetUp №13
IPython pdb
https://github.com/gotcha/ipdb
Инструменты для отладки
Moscow Django MeetUp №13
ipdb
подсветка кода
автодополнение
лучше traceback и introspection
консоль (спорно)
Moscow Django MeetUp №13
ipdbplugin
https://github.com/flavioamieiro/nose-ipdb
Инструменты для отладки
Moscow Django MeetUp №13
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ pip install ipdbplugin
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ nosetests --ipdb
rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔)
➜ nosetests --ipdb-failures
ipdbplugin
Moscow Django MeetUp №13
PyCharm
http://www.jetbrains.com/pycharm/
Инструменты для отладки
Moscow Django MeetUp №13
PyCharm
Moscow Django MeetUp №13
PyCharm
отладка прямо в редакторе
установка breakpoint кликом мышки
GUI (спорно)
Moscow Django MeetUp №13
Пожалуй, хватит
Moscow Django MeetUp №13
Вопросы?
Moscow Django MeetUp №13
Контакты
•Владимир Рудных
• rudnyh@corp.mail.ru
• github.com/dreadatour
• dreadatour.habrahabr.ru

Contenu connexe

Tendances

Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.Roman Brovko
 
Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.Roman Brovko
 
Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.Roman Brovko
 
Лекция 10. Классы 2.
Лекция 10. Классы 2.Лекция 10. Классы 2.
Лекция 10. Классы 2.Roman Brovko
 
Лекция 6. Классы 1.
Лекция 6. Классы 1.Лекция 6. Классы 1.
Лекция 6. Классы 1.Roman Brovko
 
Лекция 7. Исключения и менеджеры контекста.
Лекция 7. Исключения и менеджеры контекста.Лекция 7. Исключения и менеджеры контекста.
Лекция 7. Исключения и менеджеры контекста.Roman Brovko
 
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014Python Meetup
 
Лекция 11. Тестирование.
Лекция 11. Тестирование.Лекция 11. Тестирование.
Лекция 11. Тестирование.Roman Brovko
 
Магия в Python: Дескрипторы. Что это?
Магия в Python: Дескрипторы. Что это?Магия в Python: Дескрипторы. Что это?
Магия в Python: Дескрипторы. Что это?PyNSK
 
Красота и изящность стандартной библиотеки Python
Красота и изящность стандартной библиотеки PythonКрасота и изящность стандартной библиотеки Python
Красота и изящность стандартной библиотеки PythonPython Meetup
 
Лекция 4. Строки, байты, файлы и ввод/вывод.
 Лекция 4. Строки, байты, файлы и ввод/вывод. Лекция 4. Строки, байты, файлы и ввод/вывод.
Лекция 4. Строки, байты, файлы и ввод/вывод.Roman Brovko
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Vasya Petrov
 
Магия метаклассов
Магия метаклассовМагия метаклассов
Магия метаклассовAndrey Zakharevich
 
Лекция 8. Итераторы, генераторы и модуль itertools.
 Лекция 8. Итераторы, генераторы и модуль itertools. Лекция 8. Итераторы, генераторы и модуль itertools.
Лекция 8. Итераторы, генераторы и модуль itertools.Roman Brovko
 
Лекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GILЛекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GILRoman Brovko
 
Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Roman Brovko
 
8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)Smolensk Computer Science Club
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPython Meetup
 
Python dict: прошлое, настоящее, будущее
Python dict: прошлое, настоящее, будущееPython dict: прошлое, настоящее, будущее
Python dict: прошлое, настоящее, будущееdelimitry
 

Tendances (20)

Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.
 
Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.
 
Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.
 
Лекция 10. Классы 2.
Лекция 10. Классы 2.Лекция 10. Классы 2.
Лекция 10. Классы 2.
 
Лекция 6. Классы 1.
Лекция 6. Классы 1.Лекция 6. Классы 1.
Лекция 6. Классы 1.
 
Лекция 7. Исключения и менеджеры контекста.
Лекция 7. Исключения и менеджеры контекста.Лекция 7. Исключения и менеджеры контекста.
Лекция 7. Исключения и менеджеры контекста.
 
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
 
Лекция 11. Тестирование.
Лекция 11. Тестирование.Лекция 11. Тестирование.
Лекция 11. Тестирование.
 
Магия в Python: Дескрипторы. Что это?
Магия в Python: Дескрипторы. Что это?Магия в Python: Дескрипторы. Что это?
Магия в Python: Дескрипторы. Что это?
 
Красота и изящность стандартной библиотеки Python
Красота и изящность стандартной библиотеки PythonКрасота и изящность стандартной библиотеки Python
Красота и изящность стандартной библиотеки Python
 
Лекция 4. Строки, байты, файлы и ввод/вывод.
 Лекция 4. Строки, байты, файлы и ввод/вывод. Лекция 4. Строки, байты, файлы и ввод/вывод.
Лекция 4. Строки, байты, файлы и ввод/вывод.
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1
 
Магия метаклассов
Магия метаклассовМагия метаклассов
Магия метаклассов
 
Лекция 8. Итераторы, генераторы и модуль itertools.
 Лекция 8. Итераторы, генераторы и модуль itertools. Лекция 8. Итераторы, генераторы и модуль itertools.
Лекция 8. Итераторы, генераторы и модуль itertools.
 
Лекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GILЛекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GIL
 
Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.
 
8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)
 
Charming python sc2-8
Charming python sc2-8Charming python sc2-8
Charming python sc2-8
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стиль
 
Python dict: прошлое, настоящее, будущее
Python dict: прошлое, настоящее, будущееPython dict: прошлое, настоящее, будущее
Python dict: прошлое, настоящее, будущее
 

Similaire à Профилирование и отладка Django

20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonovComputer Science Club
 
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...Yandex
 
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Yandex
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioAndrey Karpov
 
Опыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаОпыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаAndrey Karpov
 
Лекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPЛекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPMikhail Kurnosov
 
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)Mikhail Kurnosov
 
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)Mikhail Kurnosov
 
Всё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программистаВсё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программистаAndrey Karpov
 
Сверхоптимизация кода на Python
Сверхоптимизация кода на PythonСверхоптимизация кода на Python
Сверхоптимизация кода на Pythonru_Parallels
 
Сверхоптимизация кода на Python
Сверхоптимизация кода на PythonСверхоптимизация кода на Python
Сверхоптимизация кода на PythonCodeFest
 
Статический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минутСтатический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минутAndrey Karpov
 
Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Andrey Karpov
 
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...Yandex
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыcorehard_by
 
FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»
FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»
FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»Yandex
 
Юнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, GoogleЮнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, Googleyaevents
 
Алексей Андросов - Debugger: Отладка кода
Алексей Андросов - Debugger: Отладка кодаАлексей Андросов - Debugger: Отладка кода
Алексей Андросов - Debugger: Отладка кодаYandex
 
Михаил Матросов, “С++ без new и delete”
Михаил Матросов, “С++ без new и delete”Михаил Матросов, “С++ без new и delete”
Михаил Матросов, “С++ без new и delete”Platonov Sergey
 
Полный цикл тестирования React-приложений, Алексей Андросов и Наталья Стусь
Полный цикл тестирования React-приложений, Алексей Андросов и Наталья СтусьПолный цикл тестирования React-приложений, Алексей Андросов и Наталья Стусь
Полный цикл тестирования React-приложений, Алексей Андросов и Наталья СтусьMail.ru Group
 

Similaire à Профилирование и отладка Django (20)

20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
 
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...
 
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
 
Опыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаОпыт разработки статического анализатора кода
Опыт разработки статического анализатора кода
 
Лекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPЛекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMP
 
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
 
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
 
Всё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программистаВсё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программиста
 
Сверхоптимизация кода на Python
Сверхоптимизация кода на PythonСверхоптимизация кода на Python
Сверхоптимизация кода на Python
 
Сверхоптимизация кода на Python
Сверхоптимизация кода на PythonСверхоптимизация кода на Python
Сверхоптимизация кода на Python
 
Статический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минутСтатический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минут
 
Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?
 
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтеры
 
FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»
FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»
FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»
 
Юнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, GoogleЮнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, Google
 
Алексей Андросов - Debugger: Отладка кода
Алексей Андросов - Debugger: Отладка кодаАлексей Андросов - Debugger: Отладка кода
Алексей Андросов - Debugger: Отладка кода
 
Михаил Матросов, “С++ без new и delete”
Михаил Матросов, “С++ без new и delete”Михаил Матросов, “С++ без new и delete”
Михаил Матросов, “С++ без new и delete”
 
Полный цикл тестирования React-приложений, Алексей Андросов и Наталья Стусь
Полный цикл тестирования React-приложений, Алексей Андросов и Наталья СтусьПолный цикл тестирования React-приложений, Алексей Андросов и Наталья Стусь
Полный цикл тестирования React-приложений, Алексей Андросов и Наталья Стусь
 

Профилирование и отладка Django

  • 2. Moscow Django MeetUp №13 Обо мне • технический руководитель Календаря Mail.Ru • pythonista • бывший перловик • ленивый программист
  • 3. Moscow Django MeetUp №13 Cбор характеристик работы программы с целью их дальнейшей оптимизации. Профилирование
  • 4. Moscow Django MeetUp №13 Что собираем? • время выполнения строк кода • количество вызовов функций • время выполнения функций • дерево вызовов функций • “hot spots” • загрузку CPU, использование памяти • и т.д.
  • 5. Moscow Django MeetUp №13 Project Euler http://projecteuler.net Тренируемся
  • 6. Moscow Django MeetUp №13 Простые делители числа 13195 — это 5, 7, 13 и 29. Какой самый большой делитель числа 600851475143, являющийся простым числом? Project Euler: задача 3
  • 7. Moscow Django MeetUp №13 1 """Project Euler problem 3 solve""" 2 3 4 def is_prime(num): 5 """Checks if num is prime number""" 6 for i in range(2, num): 7 if not num % i: 8 return False 9 return True 10 11 12 def prime_factors(num): 13 """Find prime factors of num""" 14 result = [] 15 for i in range(2, num): 16 if is_prime(i) and not num % i: 17 result.append(i) 18 return result 19 20 21 if __name__ == '__main__': 22 print "Answer: %d" % prime_factors(600851475143)[-1] Project Euler: задача 3
  • 10. Moscow Django MeetUp №13 Профилирование начинается в голове. Инструменты — всего лишь инструменты. Искусство профилирования
  • 11. Moscow Django MeetUp №13 1 """Project Euler problem 3 solve""" 2 from math import sqrt 3 4 5 def is_prime(num): 6 """Checks if num is prime number""" 7 for i in range(2, int(sqrt(num)) + 1): 8 if not num % i: 9 return False 10 return True 11 12 13 def prime_factors(num): 14 """Find prime factors of num""" 15 result = [] 16 for i in range(2, int(sqrt(num)) + 1): 17 if is_prime(i) and not num % i: 18 result.append(i) 19 return result 20 21 22 if __name__ == '__main__': 23 print "Answer: %d" % prime_factors(600851475143)[-1] Project Euler: задача 3
  • 12. Moscow Django MeetUp №13 Подходы к профилированию • ручное профилирование • с помощью инструментов
  • 13. Moscow Django MeetUp №13 Ручное профилирование
  • 14. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ time python max_prime_factor.py Answer: 6857 python max_prime_factor.py 20,00s user 0,19s system 82% cpu 24,445 total Ручное профилирование
  • 15. Moscow Django MeetUp №13 1 """Project Euler problem 3 solve""" 2 import time 3 from math import sqrt 4 5 6 def is_prime(num): 7 """Checks if num is prime number""" 8 for i in range(2, int(sqrt(num)) + 1): 9 if not num % i: 10 return False 11 return True 12 13 14 def prime_factors(num): 15 """Find prime factors of num""" 16 result = [] 17 for i in range(2, int(sqrt(num)) + 1): 18 if is_prime(i) and not num % i: 19 result.append(i) 20 return result 21 22 23 if __name__ == '__main__': 24 start = time.time() 25 print "Answer: %d" % prime_factors(600851475143)[-1] 26 print "Time: %f s" % (time.time() - start) Ручное профилирование
  • 16. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python max_prime_factor.py Answer: 6857 Time: 23.531779 s Ручное профилирование
  • 17. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python max_prime_factor.py Answer: 6857 Time: 21.143574 s rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python max_prime_factor.py Answer: 6857 Time: 22.638407 s rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python max_prime_factor.py Answer: 6857 Time: 20.774542 s rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python max_prime_factor.py Answer: 6857 Time: 22.272329 s rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python max_prime_factor.py Answer: 6857 Time: 23.562760 s Ручное профилирование
  • 18. Moscow Django MeetUp №13 timeit http://docs.python.org/2/library/timeit.html Ручное профилирование
  • 19. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python -m timeit -n 10 -s'from max_prime_factor import prime_factors' 'prime_factors(600851475143)' 10 loops, best of 3: 22.3 sec per loop timeit
  • 20. Moscow Django MeetUp №13 Ручное профилирование очень простое применение ограниченно подходит для продакшена вставка чужеродного кода в проект никакой информации о коде (кроме времени выполнения) анализ результатов может быть затруднительным
  • 21. Moscow Django MeetUp №13 — Зацени, мой код быстрее твоего! Применение
  • 22. Moscow Django MeetUp №13 Применение
  • 23. Moscow Django MeetUp №13 Сбор статистики времени выполнения кода. Например, в graphite или statsd: Применение в реальной жизни
  • 24. Moscow Django MeetUp №13 1 """Collect profiling statistic into graphite""" 2 import socket 3 import time 4 5 6 CARBON_SERVER = '127.0.0.1' 7 CARBON_PORT = 2003 8 9 10 class Stats(object): 11 """Context manager for send stats to graphite""" 12 13 def __init__(self, name): 14 self.name = name 15 16 def __enter__(self): 17 self.start = time.time() 18 return self 19 20 def __exit__(self, *args): 21 duration = (time.time() - self.start) * 1000 # msec 22 message = '%s %d %dn' % (self.name, duration, time.time()) 23 24 sock = socket.socket() 25 sock.connect((CARBON_SERVER, CARBON_PORT)) 26 sock.sendall(message) 27 sock.close() Менеджер контекста
  • 25. Moscow Django MeetUp №13 from django.core.mail import send_mail from profiling.context_managers import Stats ... with Stats('django_project.profiling.send_email'): send_mail( 'Subject here', 'Here is the message.', 'from@example.com', ['to@example.com'], fail_silently=False ) Пример использования
  • 26. Moscow Django MeetUp №13 1 """Collect profiling statistic into graphite""" 2 import socket 3 import time 4 5 6 CARBON_SERVER = '127.0.0.1' 7 CARBON_PORT = 2003 8 9 10 def stats(name): 11 """Decorator for send stats to graphite""" 12 def _timing(func): 13 def _wrapper(*args, **kwargs): 14 start = time.time() 15 result = func(*args, **kwargs) 16 duration = (time.time() - start) * 1000 # msec 17 message = '%s %d %dn' % (name, duration, time.time()) 18 19 sock = socket.socket() 20 sock.connect((CARBON_SERVER, CARBON_PORT)) 21 sock.sendall(message) 22 sock.close() 23 24 return result 25 return _wrapper 26 return _timing Декоратор
  • 27. Moscow Django MeetUp №13 from django.db import models from profiling.decorator import stats ... class Model(model.Model): ... @stats('django_project.profiling.application.save') def save(self, *args, **kwargs): # do some hard work like thumbnail generation super(Model, self).save(*args, **kwargs) Пример использования
  • 28. Moscow Django MeetUp №13 Статистика профилирования
  • 29. Moscow Django MeetUp №13 Профилирование с помощью инструментов
  • 30. Moscow Django MeetUp №13 Инструменты для профилирования •Deterministic (event-based) •Statistical
  • 31. Moscow Django MeetUp №13 def is_prime(num): """Checks if num is prime number""" for i in range(2, num): if not num % i: return False return True Deterministic profilers @profile def is_prime(num): """Checks if num is prime number""" for i in range(2, num): if not num % i: return False return True
  • 32. Moscow Django MeetUp №13 def is_prime(num): """Checks if num is prime number""" with profile(): for i in range(2, num): if not num % i: return False return True Deterministic profilers def is_prime(num): """Checks if num is prime number""" profile.start() for i in range(2, num): if not num % i: return False profile.stop() return True
  • 33. Moscow Django MeetUp №13 Deterministic profilers def foo() def bar() def baz() def ololo()
  • 34. Moscow Django MeetUp №13 Deterministic profilers вся информация о коде множество инструментов для анализа очень медленно непригодно для продакшена (или крайне ограниченно)
  • 35. Moscow Django MeetUp №13 Statistical profilers def foo() def bar() def baz() def foo() def bar() def baz() Timer: 1ms Timer: 10ms
  • 36. Moscow Django MeetUp №13 Statistical profilers def foo() def foo() def foo() def foo()def foo() def foo()
  • 37. Moscow Django MeetUp №13 Statistical profilers можно пускать в продакшн (практически не влияет на быстродействие) не вся информация о коде мало инструментов для анализа
  • 38. Moscow Django MeetUp №13 Deterministic profilers • profile • cProfile • hotshot • kcachegrind • RunSnakeRun • gprof2dot • pycallgraph • line_profiler • memory_profiler • dowser • guppy • muppy • memprof • objgraph “тысячи их”...
  • 39. Moscow Django MeetUp №13 cProfile http://docs.python.org/2/library/profile.html Инструменты для профилирования
  • 40. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python -m cProfile -s time max_prime_factor.py Answer: 6857 2325444 function calls in 21.912 seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 775145 14.240 0.000 21.233 0.000 max_prime_factor.py:5(is_prime) 775146 6.779 0.000 6.779 0.000 {range} 1 0.630 0.630 21.909 21.909 max_prime_factor.py:13(prime_factors) 775146 0.260 0.000 0.260 0.000 {math.sqrt} 1 0.003 0.003 21.912 21.912 max_prime_factor.py:1(<module>) 4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects} 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} cProfile
  • 41. Moscow Django MeetUp №13 1 """Project Euler problem 3 solve""" 2 from math import sqrt 3 4 5 def is_prime(num): 6 """Checks if num is prime number""" 7 for i in range(2, int(sqrt(num)) + 1): 8 if not num % i: 9 return False 10 return True 11 12 13 def prime_factors(num): 14 """Find prime factors of num""" 15 result = [] 16 for i in range(2, int(sqrt(num)) + 1): 17 if is_prime(i) and not num % i: 18 result.append(i) 19 return result 20 21 22 if __name__ == '__main__': 23 print "Answer: %d" % prime_factors(600851475143)[-1] Project Euler: задача 3
  • 42. Moscow Django MeetUp №13 1 """Project Euler problem 3 solve""" 2 from math import sqrt 3 4 5 def is_prime(num): 6 """Checks if num is prime number""" 7 for i in range(2, int(sqrt(num)) + 1): 8 if not num % i: 9 return False 10 return True 11 12 13 def prime_factors(num): 14 """Find prime factors of num""" 15 result = [] 16 for i in range(2, int(sqrt(num)) + 1): 17 if not num % i and is_prime(i): 18 result.append(i) 19 return result 20 21 22 if __name__ == '__main__': 23 print "Answer: %d" % prime_factors(600851475143)[-1] Project Euler: задача 3
  • 43. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python -m cProfile -s time max_prime_factor.py Answer: 6857 30 function calls in 0.225 seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 1 0.179 0.179 0.250 0.250 max_prime_factor.py:13(prime_factors) 8 0.070 0.009 0.070 0.009 {range} 1 0.003 0.003 0.253 0.253 max_prime_factor.py:1(<module>) 7 0.000 0.000 0.000 0.000 max_prime_factor.py:5(is_prime) 8 0.000 0.000 0.000 0.000 {math.sqrt} 4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects} 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} cProfile
  • 44. Moscow Django MeetUp №13 Ускорил код в сто раз
  • 45. Moscow Django MeetUp №13 import cProfile def profile(func): """Decorator for run function profile""" def wrapper(*args, **kwargs): profile_filename = func.__name__ + '.profile' profiler = cProfile.Profile() result = profiler.runcall(func, *args, **kwargs) profiler.dump_stats(profile_filename) return result return wrapper @profile def foo(): ... cProfile: декоратор
  • 46. Moscow Django MeetUp №13 hotshot http://docs.python.org/2/library/hotshot.html Инструменты для профилирования
  • 47. Moscow Django MeetUp №13 import hotshot prof = hotshot.Profile("profile_name.prof") prof.start() # your code goes here prof.stop() prof.close() hotshot: использование
  • 48. Moscow Django MeetUp №13 import hotshot def profile(func): """Decorator for run function profile""" def wrapper(*args, **kwargs): profile_filename = func.__name__ + '.profile' profiler = hotshot.Profile(profile_filename) profiler.start() result = func(*args, **kwargs) profiler.stop() profiler.close() return result return wrapper @profile def foo(): ... hotshot: декоратор
  • 49. Moscow Django MeetUp №13 cProfile, hotshot мощные инструменты достаточно простые дерево вызовов функций сильно влияют на производительность анализ результатов может быть затруднительным
  • 50. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ time python max_prime_factor.py Answer: 6857 python max_prime_factor.py 0,18s user 0,01s system 95% cpu 0,199 total rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ time python -m cProfile max_prime_factor.py Answer: 6857 22 function calls in 0.252 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.005 0.005 0.252 0.252 max_prime_factor.py:1(<module>) 1 0.247 0.247 0.247 0.247 max_prime_factor.py:13(prime_factors) 7 0.000 0.000 0.000 0.000 max_prime_factor.py:5(is_prime) 8 0.000 0.000 0.000 0.000 {math.sqrt} 4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects} 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} python -m cProfile max_prime_factor.py 0,23s user 0,09s system 58% cpu 0,541 total cProfile: производительность
  • 51. Moscow Django MeetUp №13 Сохраняем результаты профилирования в файл для дальнейшего анализа: rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python -m cProfile -o max_prime_factor.prof max_prime_factor.py Answer: 6857 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ ls max_prime_factor.prof max_prime_factor.py cProfile: анализ результатов
  • 52. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ ipython In [1]: import pstats In [2]: p = pstats.Stats('max_prime_factor.prof') In [3]: p.sort_stats('calls') Out[3]: <pstats.Stats instance at 0x10689bf80> In [4]: p.print_stats(5) 22 function calls in 0.166 seconds Ordered by: call count List reduced from 6 to 5 due to restriction <5> ncalls tottime percall cumtime percall filename:lineno(function) 8 0.000 0.000 0.000 0.000 {math.sqrt} 7 0.000 0.000 0.000 0.000 max_prime_factor.py:5(is_prime) 4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects} 1 0.003 0.003 0.166 0.166 max_prime_factor.py:1(<module>) 1 0.163 0.163 0.163 0.163 max_prime_factor.py:13(prime_factors) Out[4]: <pstats.Stats instance at 0x10689bf80> Анализ: pstats
  • 53. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ pip install pyprof2calltree rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ pyprof2calltree -i max_prime_factor.prof -o max_prime_factor.kgrind rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ pyprof2calltree -i max_prime_factor.prof -k Анализ: kcachegrind
  • 54. Moscow Django MeetUp №13 Анализ: kcachegrind
  • 55. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ brew install wxwidgets rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ pip install SquareMap RunSnakeRun rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ runsnake max_prime_factor.prof Анализ: RunSnakeRun
  • 56. Moscow Django MeetUp №13 Анализ: RunSnakeRun
  • 57. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ brew install graphviz rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ pip install gprof2dot rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ gprof2dot -f pstats max_prime_factor.prof | dot -Tpng -o max_prime_factor.png Анализ: gprof2dot
  • 58. Moscow Django MeetUp №13 Анализ: gprof2dot
  • 59. Moscow Django MeetUp №13 Но где же Django?
  • 60. Moscow Django MeetUp №13 Профилируем Django • Устанавливаем модуль: ➜ pip install django-extensions • Добавляем application в Django: INSTALLED_APPS += ('django_extensions',) • Запускаем тестовый сервер: ➜ python manage.py runprofileserver --use-cprofile --prof-path=/tmp/prof/
  • 61. Moscow Django MeetUp №13 Получаем по одному *.prof файлу на запрос: rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ ls /tmp/prof/ admin.000276ms.1374075009.prof admin.account.user.000278ms.1374075014.prof admin.jsi18n.000185ms.1374075018.prof favicon.ico.000017ms.1374075001.prof root.000073ms.1374075004.prof static.admin.css.base.css.000011ms.1374075010.prof static.admin.css.forms.css.000013ms.1374075017.prof static.admin.img.icon-yes.gif.000001ms.1374075015.prof static.admin.img.sorting-icons.gif.000001ms.1374075015.prof static.admin.js.core.js.000018ms.1374075014.prof static.admin.js.jquery.js.000003ms.1374075014.prof static.css.bootstrap-2.3.2.min.css.000061ms.1374074996.prof static.img.glyphicons-halflings.png.000001ms.1374075005.prof static.js.bootstrap-2.3.2.min.js.000004ms.1374074996.prof static.js.jquery-2.0.2.min.js.000001ms.1374074996.prof user.login.000187ms.1374075001.prof А дальшё всё как обычно: Профилируем Django
  • 62. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ ipython In [1]: import pstats In [2]: p = pstats.Stats('/tmp/prof/user.login.000187ms.1374075001.prof') In [3]: p.sort_stats('calls') Out[3]: <pstats.Stats instance at 0x107efa5f0> In [4]: p.print_stats(5) 36854 function calls (35710 primitive calls) in 0.187 seconds Ordered by: call count List reduced from 774 to 5 due to restriction <5> ncalls tottime percall cumtime percall filename:lineno(function) 4714 0.002 0.000 0.002 0.000 {method 'append' of 'list' objects} 3562 0.003 0.000 0.003 0.000 {isinstance} 2456 0.003 0.000 0.003 0.000 {method 'startswith' of 'unicode' objects} 1058/1048 0.002 0.000 0.002 0.000 {getattr} 979/962 0.000 0.000 0.025 0.000 {len} Out[4]: <pstats.Stats instance at 0x107efa5f0> Анализ: pstats
  • 63. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ pyprof2calltree -i /tmp/prof/user.login.000187ms.1374075001.prof -k Анализ: kcachegrind
  • 64. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ runsnake /tmp/prof/user.login.000187ms.1374075001.prof Анализ: RunSnakeRun
  • 65. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ gprof2dot -f pstats /tmp/prof/user.login.000187ms.1374075001.prof | dot -Tpng -o login.png Анализ: gprof2dot
  • 66. Moscow Django MeetUp №13 Ещё инструменты
  • 67. Moscow Django MeetUp №13 pycallgraph http://pycallgraph.slowchop.com/ Инструменты для профилирования
  • 68. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ pip install pycallgraph rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ pycallgraph max_prime_factor.py Python Call Graph v0.5.1 Starting trace Answer: 6857 Creating pycallgraph.png Done! pycallgraph
  • 69. Moscow Django MeetUp №13 import pycallgraph pycallgraph.start_trace() # your code goes here pycallgraph.make_dot_graph('call-graph.png') pycallgraph
  • 70. Moscow Django MeetUp №13 line_profiler https://bitbucket.org/robertkern/line_profiler Инструменты для профилирования
  • 71. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ kernprof.py -v -l max_prime_factor.py Function: is_prime at line 5 Total time: 0.001412 s Line # Hits Time Per Hit % Time Line Contents ============================================================== 6 def is_prime(num): 7 """Checks if num is prime number""" 8 366 767 2.1 54.3 for i in range(2, int(sqrt(num)) + 1): 9 362 614 1.7 43.5 if not num % i: 10 3 23 7.7 1.6 return False 11 4 8 2.0 0.6 return True Function: prime_factors at line 14 Total time: 2.67703 s Line # Hits Time Per Hit % Time Line Contents ============================================================== 15 def prime_factors(num): 16 """Find prime factors of num""" 17 1 4 4.0 0.0 result = [] 18 775146 1320370 1.7 49.3 for i in range(2, int(sqrt(num)) + 1): 19 775145 1356632 1.8 50.7 if not num % i and is_prime(i): 20 4 16 4.0 0.0 result.append(i) 21 1 10 10.0 0.0 return result line_profiler
  • 72. Moscow Django MeetUp №13 memory_profiler https://github.com/fabianp/memory_profiler Инструменты для профилирования
  • 73. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python -m memory_profiler max_prime_factor.py Line # Mem usage Increment Line Contents ================================================ 6 def is_prime(num): 7 32.469 MB 0.000 MB """Checks if num is prime number""" 8 57.414 MB 24.945 MB for i in range(2, int(sqrt(num)) + 1): 9 57.414 MB 0.000 MB if not num % i: 10 32.566 MB -24.848 MB return False 11 33.047 MB 0.480 MB return True Line # Mem usage Increment Line Contents ================================================ 15 def prime_factors(num): 16 8.379 MB 0.000 MB """Find prime factors of num""" 17 8.379 MB 0.000 MB result = [] 18 75.332 MB 66.953 MB for i in range(2, int(sqrt(num)) + 1): 19 33.047 MB -42.285 MB if not num % i and is_prime(i): 20 75.332 MB 42.285 MB result.append(i) 21 75.332 MB 0.000 MB return result memory_profiler
  • 74. Moscow Django MeetUp №13 1 """Project Euler problem 3 solve""" 2 from math import sqrt 3 4 5 def is_prime(num): 6 """Checks if num is prime number""" 7 for i in xrange(2, int(sqrt(num)) + 1): 8 if not num % i: 9 return False 10 return True 11 12 13 def prime_factors(num): 14 """Find prime factors of num""" 15 result = [] 16 for i in xrange(2, int(sqrt(num)) + 1): 17 if not num % i and is_prime(i): 18 result.append(i) 19 return result 20 21 22 if __name__ == '__main__': 23 print "Answer: %d" % prime_factors(600851475143)[-1] Project Euler: задача 3
  • 75. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python -m memory_profiler max_prime_factor.py Line # Mem usage Increment Line Contents ================================================ 6 def is_prime(num): 7 8.391 MB 0.000 MB """Checks if num is prime number""" 8 22.605 MB 14.215 MB for i in xrange(2, int(sqrt(num)) + 1): 9 22.605 MB 0.000 MB if not num % i: 10 8.484 MB -14.121 MB return False 11 8.965 MB 0.480 MB return True Line # Mem usage Increment Line Contents ================================================ 15 def prime_factors(num): 16 8.379 MB 0.000 MB """Find prime factors of num""" 17 8.379 MB 0.000 MB result = [] 18 34.141 MB 25.762 MB for i in xrange(2, int(sqrt(num)) + 1): 19 8.965 MB -25.176 MB if not num % i and is_prime(i): 20 34.141 MB 25.176 MB result.append(i) 21 34.141 MB 0.000 MB return result memory_profiler
  • 76. Moscow Django MeetUp №13 И ещё инструменты
  • 77. Moscow Django MeetUp №13 Профилирование памяти Dowser http://www.aminus.net/wiki/Dowser Инструменты для профилирования
  • 78. Moscow Django MeetUp №13 Профилирование памяти guppy http://guppy-pe.sourceforge.net/ Инструменты для профилирования
  • 79. Moscow Django MeetUp №13 Обнаружение утечек памяти muppy http://pythonhosted.org/Pympler/muppy.html Инструменты для профилирования
  • 80. Moscow Django MeetUp №13 Профилирование памяти memprof http://jmdana.github.io/memprof/ Инструменты для профилирования
  • 81. Moscow Django MeetUp №13 Исследование объектов objgraph http://mg.pov.lt/objgraph/ Инструменты для профилирования
  • 82. Moscow Django MeetUp №13 Statistical profilers • StatProf • Plop • New Relic
  • 83. Moscow Django MeetUp №13 statprof https://github.com/bos/statprof.py Инструменты для профилирования
  • 84. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ pip install statprof import statprof statprof.start() try: function() finally: statprof.stop() statprof.display() import statprof with statprof.profile(): function() statprof
  • 85. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ time python max_prime_factor.py Answer: 6857 python max_prime_factor.py 10,42s user 0,04s system 97% cpu 10,750 total rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ time python max_prime_factor.py Answer: 6857 % cumulative self time seconds seconds name 83.03 8.82 8.82 max_prime_factor.py:9:is_prime 13.52 1.44 1.44 max_prime_factor.py:8:is_prime 2.01 10.62 0.21 max_prime_factor.py:18:prime_factors 0.88 0.09 0.09 max_prime_factor.py:6:is_prime 0.48 0.05 0.05 max_prime_factor.py:10:is_prime 0.06 0.01 0.01 max_prime_factor.py:11:is_prime 0.03 10.62 0.00 max_prime_factor.py:26:<module> --- Sample count: 3535 Total time: 10.620000 seconds python max_prime_factor.py 10,56s user 0,17s system 90% cpu 11,908 total statprof
  • 86. Moscow Django MeetUp №13 statprof • Устанавливаем zeromq (нужна для работы): ➜ brew install zmq • Устанавливаем модуль: ➜ pip install statprof django-live-profiler • Запускаем аггрегатор: ➜ aggregated --host 127.0.0.1 --port 5556
  • 87. Moscow Django MeetUp №13 statprof • Добавляем application в Django: INSTALLED_APPS += ('profiler',) • Добавляем middleware: MIDDLEWARE_CLASSES += ( 'profiler.middleware.ProfilerMiddleware', 'profiler.middleware.StatProfMiddleware') • Добавляем urls: url(r'^profiler/', include('profiler.urls')) • Запускаем Django: ➜ python manage.py runserver --noreload --nothreading
  • 88. Moscow Django MeetUp №13 statprof
  • 89. Moscow Django MeetUp №13 statprof
  • 90. Moscow Django MeetUp №13 statprof небольшой оверхед можно пускать в продакшн (если осторожно) профилирование SQL-запросов сложная установка, зависимости мало данных на выходе
  • 91. Moscow Django MeetUp №13 plop https://github.com/bdarnell/plop Инструменты для профилирования
  • 92. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ pip install plop tornado rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python -m plop.collector max_prime_factor.py Answer: 6857 profile output saved to /tmp/plop.out overhead was 4.78124272996e-05 per sample (0.00478124272996%) rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python -m plop.viewer --datadir=/tmp/ plop
  • 93. Moscow Django MeetUp №13 plop
  • 94. Moscow Django MeetUp №13 plop
  • 95. Moscow Django MeetUp №13 plop • Устанавливаем модули: ➜ pip install plop django-plop tornado • Добавляем application в Django: INSTALLED_APPS += ('django_plop',) • Добавляем middleware: MIDDLEWARE_CLASSES += ( 'django_plop.middleware.PlopMiddleware',) • Указываем путь для сохранения результатов: PLOP_DIR = os.path.join(ROOT_DIR, 'plop')
  • 96. Moscow Django MeetUp №13 plop • Запускаем Django: ➜ python manage.py runserver --noreload --nothreading • Запускаем просмотр результатов: ➜ python -m plop.viewer --datadir=plop
  • 97. Moscow Django MeetUp №13 plop минимальный оверхед (около 2%) можно пускать в продакшн сложная установка, зависимости очень мало данных на выходе
  • 98. Moscow Django MeetUp №13 New Relic http://newrelic.com/ Инструменты для профилирования
  • 99. Moscow Django MeetUp №13 New Relic
  • 100. Moscow Django MeetUp №13 New Relic
  • 101. Moscow Django MeetUp №13 New Relic
  • 102. Moscow Django MeetUp №13 New Relic предназначен для продакшена огромный функционал платный (есть бесплатная версия) данные отправляются на чужие серверы
  • 103. Moscow Django MeetUp №13 Django Debug Toolbar https://github.com/django-debug-toolbar/django-debug-toolbar Инструменты для профилирования
  • 104. Moscow Django MeetUp №13 Django Debug Toolbar • Устанавливаем модули: ➜ pip install django-debug-toolbar • Добавляем application в Django: INSTALLED_APPS += ('debug_toolbar',) • Добавляем middleware: MIDDLEWARE_CLASSES += ( 'debug_toolbar.middleware.DebugToolbarMiddleware',) • Указываем IP для которых показываем тулбар: INTERNAL_IPS = ('127.0.0.1',)
  • 105. Moscow Django MeetUp №13 Django Debug Toolbar
  • 106. Moscow Django MeetUp №13 Django Debug Toolbar
  • 107. Moscow Django MeetUp №13 Django Debug Toolbar
  • 108. Moscow Django MeetUp №13 Django Debug Toolbar прост в установке и использовании огромный функционал расширяемый (плагины) не для продакшена (?) данные никуда не сохраняются (только просмотр в реальном времени)
  • 109. Moscow Django MeetUp №13 Django StatsD https://github.com/andymckay/django-statsd Инструменты для профилирования
  • 110. Moscow Django MeetUp №13 Django StatsD • Устанавливаем модули: ➜ pip install django-statsd-mozilla • Добавляем application в Django: INSTALLED_APPS += ('django_statsd',) • Добавляем middleware: MIDDLEWARE_CLASSES += ( 'django_statsd.middleware.GraphiteRequestTimingMiddleware', 'django_statsd.middleware.GraphiteMiddleware',) • Указываем, что хотим получать тайминги БД: STATSD_PATCHES = ['django_statsd.patches.db']
  • 111. Moscow Django MeetUp №13 Django StatsD
  • 112. Moscow Django MeetUp №13 Django StatsD прост в установке и использовании используется в продакшене мало информации (количество/время) Нужен graphite и statsd (must-have)
  • 113. Moscow Django MeetUp №13 Обнаружение, локализация и устранение ошибок. Отладка
  • 114. Moscow Django MeetUp №13 The Python Debugger http://docs.python.org/2/library/pdb.html Инструменты для отладки
  • 115. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python -m pdb max_prime_factor.py > /home/rudnyh/work/python-profiling/max_prime_factor.py(1)<module>() -> """Project Euler problem 3 solve""" (Pdb) next > /home/rudnyh/work/python-profiling/max_prime_factor.py(2)<module>() -> from math import sqrt (Pdb) next > /home/rudnyh/work/python-profiling/max_prime_factor.py(5)<module>() -> def is_prime(num): (Pdb) next > /home/rudnyh/work/python-profiling/max_prime_factor.py(13)<module>() -> def prime_factors(num): (Pdb) next > /home/rudnyh/work/python-profiling/max_prime_factor.py(22)<module>() -> if __name__ == '__main__': (Pdb) next > /home/rudnyh/work/python-profiling/max_prime_factor.py(23)<module>() -> print "Answer: %d" % prime_factors(600851475143)[-1] (Pdb) next Answer: 6857 --Return-- > /home/rudnyh/work/python-profiling/max_prime_factor.py(23)<module>()->None -> print "Answer: %d" % prime_factors(600851475143)[-1] (Pdb) quit pdb
  • 116. Moscow Django MeetUp №13 1 """Project Euler problem 3 solve""" 2 from math import sqrt 3 4 5 def is_prime(num): 6 """Checks if num is prime number""" 7 import pdb; pdb.set_trace() 8 for i in xrange(2, int(sqrt(num)) + 1): 9 if not num % i: 10 return False 11 return True 12 13 14 def prime_factors(num): 15 """Find prime factors of num""" 16 result = [] 17 for i in xrange(2, int(sqrt(num)) + 1): 18 if not num % i and is_prime(i): 19 result.append(i) 20 return result 21 22 23 if __name__ == '__main__': 24 print "Answer: %d" % prime_factors(600851475143)[-1] pdb
  • 117. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python max_prime_factor.py > /home/rudnyh/work/python-profiling/max_prime_factor.py(8)is_prime() -> for i in xrange(2, int(sqrt(num)) + 1): (Pdb) list 3 4 5 def is_prime(num): 6 """Checks if num is prime number""" 7 import pdb; pdb.set_trace() 8 -> for i in xrange(2, int(sqrt(num)) + 1): 9 if not num % i: 10 return False 11 return True 12 13 (Pdb) next > /home/rudnyh/work/python-profiling/max_prime_factor.py(9)is_prime() -> if not num % i: (Pdb) continue > /home/rudnyh/work/python-profiling/max_prime_factor.py(8)is_prime() -> for i in xrange(2, int(sqrt(num)) + 1): (Pdb) pdb
  • 118. Moscow Django MeetUp №13 pdb практически неограниченный функционал не очень удобно
  • 119. Moscow Django MeetUp №13 django-pdb https://github.com/tomchristie/django-pdb Инструменты для отладки
  • 120. Moscow Django MeetUp №13 django-pdb • Устанавливаем модули: ➜ pip install django-pdb • Добавляем application в Django: INSTALLED_APPS += ('django_pdb',) • Добавляем middleware: MIDDLEWARE_CLASSES += ('django_pdb.middleware.PdbMiddleware',)
  • 121. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python manage.py runserver rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python manage.py runserver --pdb rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python manage.py runserver --ipdb rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ python manage.py runserver --pm django-pdb
  • 122. Moscow Django MeetUp №13 IPython pdb https://github.com/gotcha/ipdb Инструменты для отладки
  • 123. Moscow Django MeetUp №13 ipdb подсветка кода автодополнение лучше traceback и introspection консоль (спорно)
  • 124. Moscow Django MeetUp №13 ipdbplugin https://github.com/flavioamieiro/nose-ipdb Инструменты для отладки
  • 125. Moscow Django MeetUp №13 rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ pip install ipdbplugin rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ nosetests --ipdb rudnyh@work:~/work/python-profiling (venv: python-profiling) (git: master|✔) ➜ nosetests --ipdb-failures ipdbplugin
  • 126. Moscow Django MeetUp №13 PyCharm http://www.jetbrains.com/pycharm/ Инструменты для отладки
  • 127. Moscow Django MeetUp №13 PyCharm
  • 128. Moscow Django MeetUp №13 PyCharm отладка прямо в редакторе установка breakpoint кликом мышки GUI (спорно)
  • 129. Moscow Django MeetUp №13 Пожалуй, хватит
  • 130. Moscow Django MeetUp №13 Вопросы?
  • 131. Moscow Django MeetUp №13 Контакты •Владимир Рудных • rudnyh@corp.mail.ru • github.com/dreadatour • dreadatour.habrahabr.ru