Введение
Примеры
Профилирование кода
Прежде всего вы должны быть в состоянии найти узкое место в вашем скрипте и заметить, что никакая оптимизация не может компенсировать плохой выбор в структуре данных или недостаток в вашем алгоритме. Во-вторых, не пытайтесь оптимизировать процесс кодирования слишком рано в ущерб удобочитаемости / дизайну / качеству. Дональд Кнут сделал следующее заявление об оптимизации:
«Мы должны забыть о малой эффективности, скажем, в 97% случаев: преждевременная оптимизация - корень всего зла. Но мы не должны упускать наши возможности в эти критические 3%»
Для профилирования кода у вас есть несколько инструментов: cProfile
(или медленнее , в profile
) из стандартной библиотеки, line_profiler
и timeit
.Каждый из них служит своей цели.
cProfile
является determistic профилировщика: вызов функции, обратные функции, а также исключение события контролируются, и точные тайминги сделаны для интервалов между этими событиями (до 0.001s). Документация библиотеки ( https://docs.python.org/2/library/profile.html ) дает нам простой прецеденту
import cProfile
def f(x):
return "42!"
cProfile.run('f(12)')
Или, если вы предпочитаете оборачивать части существующего кода:
import cProfile, pstats, StringIO
pr = cProfile.Profile()
pr.enable()
# ... do something ...
# ... long ...
pr.disable()
sortby = 'cumulative'
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats()
print s.getvalue()
Это создаст выходные данные, похожие на таблицу ниже, где вы сможете быстро увидеть, где ваша программа проводит большую часть своего времени, и определить функции для оптимизации.
3 function calls in 0.000 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 <stdin>:1(f)
1 0.000 0.000 0.000 0.000 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
Модуль line_profiler
( https://github.com/rkern/line_profiler ) полезно иметь линию по анализу линии вашего кода. Это явно не поддается управлению длинными сценариями, но нацелено на фрагменты кода. Смотрите документацию для более подробной информации. Самый простой способ начать работу - использовать скрипт kernprof, как объяснено на странице пакета, обратите внимание, что вам нужно будет вручную указать функции для профилирования.
$ kernprof -l script_to_profile.py
kernprof создаст экземпляр LineProfiler и вставить его в __builtins__
пространство имен с профилем именем. Она была написана для использования в качестве декоратора, поэтому в сценарии, вы украшаете функции , которые вы хотите , чтобы профиль с @profile
.
@profile
def slow_function(a, b, c):
...
Поведение по умолчанию kernprof должен поместить результаты в бинарный файл script_to_profile.py.lprof
.Вы можете указать kernprof немедленно просмотреть отформатированные результаты на терминале с опцией [-v / - view]. В противном случае вы можете просмотреть результаты позже так:
$ python -m line_profiler script_to_profile.py.lprof
Наконец timeit
обеспечивает простой способ проверить один лайнеры или небольшое выражение как из командной строки и питон оболочки. Этот модуль будет отвечать на такие вопросы , как, это быстрее , чтобы сделать список понимание или использовать встроенный в list()
при преобразовании набора в список. Посмотрите на setup
ключевого слова или -s
вариант , чтобы добавить код установки.
>>> import timeit
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
0.8187260627746582
из терминала
$ python -m timeit '"-".join(str(n) for n in range(100))'
10000 loops, best of 3: 40.3 usec per loop