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

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

Anna | 16.06.2014 | нет комментариев
Некоторое время назад я рассказывал о «Профилировании и отладке Django». Позже выступления я получил много вопросов (как лично, так и по email), с парой новых знакомых мы даже выбрались в бар, Дабы обсудить значимые задачи программирования за кружечкой хорошего эля, со многими людьми я продолжаю общаться до сих пор.

От того что выступление вызвало живой интерес, а беседы с коллегами дозволили мне переосмыслить некоторые моменты презентации и поправить достадные ляпы, я решил оформить отчет и свои мысли в виде статьи. Это дозволит ознакомиться с темой значительно большему кругу заинтересованных лиц, к тому же Прогр предоставляет из себя совершенную площадку для комментирования предложенного материала и общения с увлекательными собеседниками.

Материала много, статья получилась большая, следственно я решил разбить её на несколько частей:

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

Вступление

В первую очередь нужно разобраться с определениями. Читаем в Википедии:

Профилирование — сбор колляций работы программы с целью их последующей оптимизации.

Выходит, для профилирования нам необходима работающая программа, причём работающая не вовсе так, как нам хотелось бы: либо работающая слишком медлительно, либо потребляющая слишком много источников.

Какие же колляции работы программы дозволено собирать?

  • время выполнения отдельных строк кода (инструкций)
  • число вызовов и время выполнения отдельных функций
  • дерево вызовов функций
  • «hot spots» (участки кода, на которые доводится значительная доля выполненных инструкций)
  • загрузку CPU и потребление памяти
  • обращение к иным источникам компьютера (скажем, к файловым дескрипторам)
  • и т.д. и т.п.

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

Давайте определимся с представлением «оптимизация». Википедия подсказывает нам, что:

Оптимизация — это модификация системы для совершенствования её результативности.

Представление «результативность» — дюже расплывчатое, и напрямую зависит от поставленной цели, скажем, в одних случаях программа должна трудиться максимально быстно, в других дозволено пренебречь скоростью и значительно значимей сэкономить оперативную память либо другие источники (такие, как диск). Как объективно сказал Фредерик Брукс, «серебрянной пули не существует».

Видимо, что оптимизацией программы дозволено заниматься безмерно: в любом довольно трудном плана неизменно найдётся тесное место, которое дозволено усовершенствовать, следственно значимо уметь останавливаться своевременно. В большинстве случаев (исключения весьма редки и относятся, скорее, кфольклору, чем к реальной жизни) нет смысла тратить, скажем, три дня рабочего времени ради 5% выигрыша по скорости.

С иной стороны, как любил повторять Дональд Кнут: «Несвоевременная оптимизация — это корень всех бед».

Какая статья про оптимизацию обходится без этой цитаты? Многие предполагают, что её автор — Дональд Кнут, но сам Дональд заявляет, что впервой её произнёс Энтони Хоар. Энтони же отпирается и предлагает считать высказывание «общим наследием».

Значимо чётко понимать, что именно нас не устраивает в работе программы и каких целей мы хотим достичь, но это не значит, что профилированием и дальнейшей оптимизацией необходимо заниматься тогда, когда всё начинает тормозить. Отличный программист неизменно знает, как себя Ощущает написанная им программа и предсказывает её работоспособность в скептических обстановках (таких, как програэффект).

Хочу подметить ещё один немаловажный момент: Зачастую оптимизация сопровождается существенным ухудшением читаемости кода. По вероятности, усердствуйте чураться этого, а в случае, если всё-таки пришлось написать менее читаемый код в критичных местах, не поленитесь и оставьте комментарий с подробным изложением его работы. Ваши сотрудники скажут вам спасибо, да и вы сами посчитаете себя ошеломительно проникновенным, когда вернётесь к этим строкам через некоторое время.

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

Подходы к профилированию

Существует, по крайней мере, три подхода к профилированию:

  • способ пристального взора
  • ручное профилирование
  • с применением инструментов

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

Превосходства и недочеты этого способа:
не требует специальных познаний и знаний
– трудно оценить трудозатраты и итог

Ручное профилирование комфортно применять, когда есть обоснованное предположение об тесных местах и требуется удостоверить либо опровергнуть догадку. Либо если нам, в различие от первого способа, необходимо получить численные показатели итогов нашей оптимизации (скажем, функция выполнялась за 946 милисекунд, стала отрабатывать за 73 милисекунды, ускорили код в 13 раз).

Суть этого способа в дальнейшем: перед выполнением спорного участка программы сберегаем в переменную нынешнее системное время (с точностью до микросекунд), а позже снова получаем нынешнее время и вычитаем из него значение сохранённой переменной. Получаем (с довольной для нас погрешностью) время выполнения анализируемого кода. Для подлинного итога повторяем N раз и берём среднее значение.

Превосходства и недочеты этого способа:
дюже примитивное использование
ограниченно подходит для продакшена
– вставка «чужеродного» кода в план
– применение допустимо не неизменно
– никакой информации о программе, помимо времени выполнения анализируемого участка
– обзор итогов может быть затруднительным

Профилирование с поддержкой инструментов помогает, когда мы (по тем либо другим причинам) не знаем, почему программа работает не так, как следует, либо когда нам лень применять ручное профилирование и исследовать его итоги. Подробнее об инструментах в дальнейшем разделе.

Должен подметить, что самостоятельно от выбранного подхода, основным инструментом разработчика остаётся его мозг. Ни одна программа (пока(?)) не скажет:
Эй, да у тебя в строке 619 файла project/app.py галиматья написана! Вынеси-ка вызов той функции из цикла и будет тебе блаженство. И ещё, если ты используешь кэширование, и перепишешь функцию calculate на Си, тогда быстродействие увеличится в среднем в 18 раз!

Какие бывают инструменты

Инструменты бывают 2-х видов (на самом деле вариантов систематизации и терминологии значительно огромнее, но мы ограничимся двумя):

  • статистический (statistical) профайлер
  • событийный (deterministic, event-based) профайлер

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

Множество разработчиков знакомы только с событийными профайлерами, и огромный неожиданностью для них оказывается тот факт, что статистический профайлер возник первым: в начале семидесятых годах прошлого века программисты компьютеров IBM/360 и IBM/370 ставили прерывание по таймеру, которое записывало нынешнее значение Program status word (PSW). Последующий обзор сохранённых данных разрешал определить проблемные участки программы.

1-й событийный профайлер возник в конце тех же семидесятых годов, это была утилита ОС Unix prof, которая показывалал время выполнения всех функций программы. через несколько лет (1982 год) возникла утилитаgprof, которая обучилась отображать граф вызовов функций.

Статистический профайлер

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

видно, функция bar()выполнялась примерно в два с половиной раза дольше, чем функции foo()baz() и какая-то безымянная инструкция.

Один из недостатков статистического профайлера заключается в том, что для приобретения адекватной статистики работы программы необходимо провести как дозволено большее (в идеале — безграничное) число измерений с как дозволено меньшим промежутком. Напротив некоторые вызовы вообще могут быть не проанализированы:

скажем, из рисунка видно, что безымянная функция не попала в выборку.

Так же трудно оценить настоящее время работы анализируемых функций. Разглядим обстановку, когда функция foo() выполняется довольно стремительно, но вызывается дюже Зачастую:

и обстановку, когда функция foo() выполняется дюже длинно, но вызывается лишь один раз:

итог работы статистического профайлера будет идентичным в обоих случаях.

Тем не менее, с поиском самых «тяжёлых» и «жгучих» мест программы статистический профайлер справляется изумительно, а его минимальное воздействие на анализируемую программe (и, как следствие, пригодность к применению в продакшене) перечёркивает все минусы. К тому же Python разрешает получить полный stacktrace для кода при семплировании и его обзор разрешает получать больше полную и подробную картину.

Превосходства и недочеты статистического профайлера:
дозволено пускать в продакшен (воздействие на анализируемую программу минимально)
– получаем вдалеке не всю информация о коде (реально только «hot spots»)
– допустимо некорректное интерпретирование итога
– требуется долгое время для сбора адекватной статистики
– немного инструментов для обзора

Событийный профайлер

Событийный профайлер отслеживает все вызовы функций, возвраты, исключения и замеряет промежутки между этими событиями. Измеренное время (совместно с информацией о соответствующих участках кода и числе вызовов) сохраняется для последующего обзора.

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

И тем не менее плюсы перевешивают минусы, напротив не было бы такого громадного многообразия разных инструментов. Просмотр итогов в комфортном интерфейсе с вероятностью обзора времени выполнения и числа вызовов всякой строки программы многого стоят, граф вызовов помогает найти недочеты в используемых алгорифмах.

Превосходства и недочеты событийных профайлеров:
не требуется метаморфозы кода
получаем всю информаци о работе программы
большое число инструментов
– в некоторых случаях профайлер меняет поведение программы
– дюже медлительно
– фактически непригодно для продакшена

В дальнейшей статье мы на практике разберём ручное профилирование и статистические профайлеры. Оставайтесь на связи =)

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

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