Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Профилирование и отладка Python, переходим к практике

Anna | 16.06.2014 | нет комментариев
В прошлой статье мы определили представления профилирования и оптимизации, познакомились с разными подходами к профилированию и видами инструментов. Немножко коснулись истории профайлеров.

Сегодня я предлагаю перейти к практике и покажу на примерах методы ручного профилирования (и даже «способ пристального взора» =). Будут так же рассмотрены инструменты для статистического профилирования.

  • Вступление и теория — для чего вообще необходимо профилирование, разные подходы, инструменты и различия между ними
  • Ручное и статистическое профилирование — переходим к практике
  • Событийное профилирование — инструменты и их использование
  • Отладка — что делать, когда ничего не работает

Тренируемся

Какая может быть практика без примеров и тренировок? Я длинно думал, какой же план стоит взять в качестве учебного пособия, Дабы он был единовременно показательным и не дюже трудным. На мой взор таковым является Project Euler — альманах математических и компьютерных головоломок, от того что для решения предложенных задач доводится использовать числодробительные алгорифмы и без оптимизации поиск результата может продолжаться годами.

Вообще, дюже советую порешать головоломки из «Плана Эйлера». Помогает отвлечься, помедитировать и расслабиться, и в то же время удерживать свой мозг в тонусе.

В качестве примера для статьи возьмём задачу 3:

Примитивные делители числа 13195 — это 5, 7, 13 и 29.
Какой самый огромный делитель числа 600851475143, являющийся простым числом?

Пишем примитивное решение «в лоб»:

"""Project Euler problem 3 solve"""
from __future__ import print_function
import sys

def is_prime(num):
    """Checks if num is prime number"""
    for i in range(2, num):
        if not num % i:
            return False
    return True

def find_prime_factors(num):
    """Find prime factors of num"""
    result = []
    for i in range(2, num):
        if is_prime(i) and not num % i:
            result.append(i)
    return result

if __name__ == '__main__':
    try:
        num = int(sys.argv[1])
    except (TypeError, ValueError, IndexError):
        sys.exit("Usage: euler_3.py number")
    if num < 1:
        sys.exit("Error: number must be greater than zero")

    prime_factors = find_prime_factors(num)
    if len(prime_factors) == 0:
        print("Can't find prime factors of %d" % num)
    else:
        print("Answer: %d" % prime_factors[-1])

Внимательный либо бывалый читатель, допустимо, сходу обзовёт меня нубом, назовёт несколько задач этой программы и выдаст несколько рецептов по её оптимизации, но мы намеренно взяли примитивный пример и сделаем вид, что считаем данный код отличным, оптимизируя его по ходу действия.

Для проверки запускаем программу c числом, делители которого нам вестимы:

rudnyh@work:~/work/python-profiling (venv: python-profiling)
только тот код, тот, что работает правильно, но мы проверили работу программы на маленьком числе и результат был верный. Видимо, что задача в продуктивности и нам необходимо приступать к оптимизации.

Способ пристального взора


В реальной жизни я бы профилировал программу с доводом 13195 (когда время её работы адекватно). Но от того что мы здесь тренируемся и вообще, just for jun, воспользуемся «способом пристального взора».

Открываем код и наблюдательно на него глядим. Понимаем (если повезёт, то понимаем стремительно), что для поиска делителей числа N нам нет смысла перебирать числа из промежуткаsqrt(N) 1…N-1, т.к. все делители из этого диапазона мы теснее обнаружили при переборе чисел из промежутка 2…sqrt(N). Слегка модифицируем код (см. строки 9 и 18):

"""Project Euler problem 3 solve"""
from __future__ import print_function
import math
import sys

def is_prime(num):
    """Checks if num is prime number"""
    for i in range(2, int(math.sqrt(num))   1):
        if not num % i:
            return False
    return True

def find_prime_factors(num):
    """Find prime factors of num"""
    result = []
    for i in range(1, int(math.sqrt(num))   1):
        if is_prime(i) and not num % i:
            result.append(i)
    if is_prime(num):
        result.append(i)
    return result

if __name__ == '__main__':
    try:
        num = int(sys.argv[1])
    except (TypeError, ValueError, IndexError):
        sys.exit("Usage: euler_3.py number")
    if num < 1:
        sys.exit("Error: number must be greater than zero")

    prime_factors = find_prime_factors(num)
    if len(prime_factors) == 0:
        print("Can't find prime factors of %d" % num)
    else:
        print("Answer: %d" % prime_factors[-1])


Для проверки ещё раз запускаем программу с числом, делители которого нам вестимы:

rudnyh@work:~/work/python-profiling (venv: python-profiling)
>p://habrastorage.org/storage3/dca/265/995/dca265995d1f8aa25ba2c7214394d5a1.png”/>
по которому неизменно видно, как себя Ощущает код на живых серверах, и не пора ли его оптимизировать. Видно, как код себя Ощущает позже очередного релиза. Если проводился рефакторинг либо оптимизация, график разрешает своевременно оценить итоги и осознать, улучшилась либо ухудшилась обстановка в целом.

У способа есть и недочеты, и самый основной из них заключается в отсутствии зависимости от входных данных. Так, для функции определения простого числа «is_prime» время выполнения будет крепко зависеть от величины этого числа, и если эта функция в плане вызывается дюже Зачастую график окажется абсолютно бессмысленным. Значимо чётко понимать где какой подход дозволено применять и что мы имеем на выходе.

Безусловно, дозволено назвать способ профилирования через сбор метрик в графит «статистическим», чай мы собираем статистику работы программы. Но я предлагаю придерживаться принятой нами в первой части терминологии и под «статистическим» профилированием понимать именно сбор информации (семплирование) через определённые интервалы времени.

Django StatsD


В случае применения графита и аггрегирующего сервера (StatsD) для него мы для одной метрики получаем сразу несколько графиков: минимальное и наивысшее время выполнения кода, а так же медиану и число записанных показаний (вызовов функции) в единицу времени, что дюже комфортно. Давайте посмотрим как легко подключить StatsD к Django.

Ставим модуль:

ного итога необходим долгий обзор
– немного данных на выходе

Django-live-profiler


Отдельным пунктом стоит подметить django-live-profiler — профайлер приложений Django, использующий statprof. Для его работы нужно вначале установить zeromq:

 Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB