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

%% timeit и% timeit в IPython

Вначале убедитесь что вы работает в среду IPython, поскольку %% и % это встроенные функции. Конкатенация строки профилирования:

import string

%%timeit s=""; long_list=list(string.ascii_letters)*50
for substring in long_list:
	s+=substring
#...  
#1000 loops, best of 3: 570 us per loop

%%timeit long_list=list(string.ascii_letters)*50
s="".join(long_list)

#.....
#100000 loops, best of 3: 16.1 us per loop

Профилирование циклов по итерациям и спискам:

%timeit for i in range(100000):
	pass

# 100 loops, best of 3: 2.82 ms per loop

%timeit for i in list(range(100000)):pass
# 100 loops, best of 3: 3.95 ms per loop 

функция timeit()

Профилирование повторения элементов в массиве

import timeit

timeit.timeit('list(itertools.repeat("a", 100))', 'import itertools', number = 10000000)
$10.997665435877963

timeit.timeit('["a"]*100', number = 10000000)
# 7.118789926862576 

командная строка timeit

Профилирование конкатенации чисел

 python -m timeit "'-'.join(str(n) for n in range(100))"
10000 loops, best of 3: 29.2 usec per loop

python -m timeit "'-'.join(map(str,range(100)))"
100000 loops, best of 3: 19.4 usec per loop 

line_profiler в командной строке

Исходный код с директивой @profile перед функцией, которую мы хотим профилировать:

import requests

@profile
def slow_func():
    s = requests.session()
    html=s.get("https://en.wikipedia.org/").text
    sum([pow(ord(x),3.1) for x in list(html)])

for i in range(50):
    slow_func()

Использование команды kernprof для расчета профилирования построчно

kernprof -lv so6.py

# Wrote profile results to so6.py.lprof
# Timer unit: 4.27654e-07 s

# Total time: 22.6427 s
# File: so6.py
# Function: slow_func at line 4
#
# Line #      Hits         Time  Per Hit   % Time  Line Contents
# ==============================================================
#     4                                           @profile
#     5                                           def slow_func():
#     6        50        20729    414.6      0.0      s =

requests.session()
#     7        50     47618627 952372.5     89.9      

html=s.get("https://en.wikipedia.org/").text

#	  8        50      5306958 106139.2     10.0     

sum([pow(ord(x),3.1) for x in list(html)])

Запрос страницы почти всегда медленнее, чем любой расчет, основанный на информации на странице.

Использование cProfile (Preferred Profiler)

Python включает в себя профилировщик cProfile.Это обычно предпочтительнее, чем использование timeit.

Он разбивает весь ваш скрипт и для каждого метода в вашем скрипте говорит вам:

  • ncalls : количество раз , когда метод был вызван
  • tottime : Общее время , проведенное в данной функции ( за исключением времени , сделанное в вызовах подфункций)
  • percall : Время , затраченное на вызов. Или частное от общего времени, деленное на ncalls
  • cumtime : Совокупное время , проведенное в этом и всех подфункциях (от вызова до выхода). Эта цифра точна даже для рекурсивных функций.
  • percall : это фактор cumtime делится на примитивных вызовов
  • filename:lineno(function) : предоставляет соответствующие данные каждой функции

CProfiler можно легко вызвать из командной строки, используя:

 $ python -m cProfile main.py 

 

Чтобы отсортировать возвращенный список профилированных методов по времени, которое заняло в методе:

 $ python -m cProfile -s time main.py