Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: ehsanulОтветов: 4

Помимо ruby-prof и основного класса Benchmark, что вы используете для профилирования кода Ruby? В частности, как вы находите узкие места в своем коде? Такое ощущение, что мне нужно поработать над своим собственным маленьким инструментом, просто чтобы выяснить, на что в моем коде тратится все время.

Я понимаю, что ruby-prof предоставляет это, но вывод, откровенно говоря, очень сбивает с толку и не позволяет легко определить, какие фактические блоки вашего собственного кода являются источником проблемы (он сообщает вам о том, какие вызовы методов заняли больше всего времени хотя). Так что я получаю от этого не так много, как хотелось бы, и пока не могу этим воспользоваться.

Может я не так делаю? Есть ли альтернативы? Поиск в Google ничего мне не дает.

  • У вас те же проблемы, что и у меня в Можно ли игнорировать нерелевантные методы при профилировании приложений Ruby?. Узнала о варианте устранения метода ruby-prof. Andrew Grimm 04.11.2010

rubyprofilingprofilerruby-prof

Ответы

Ответ 1 · рейтинг 9 · Mike Dunlavey

Многие профилировщики такие. Вам нужно знать не где программа проводит время, а почему. Есть ссылки на динамический анализ кода?

ДОБАВЛЕНО: Вот как Я нахожу "узкие места" в своем коде. (Я ненавижу это слово.) Вот список причин, почему.

Совершенно естественно предположить, что для поиска "узких мест" вам нужно как-то провести много измерений. Это настолько естественно, что почти все профилировщики основаны на нем.

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

Самый простой способ объяснить это - начать с бесконечного или почти бесконечного цикла. Как вы его нашли? Вы ставите его на паузу и смотрите на стопку, верно? потому что вы знаете, что проблема где-то в стеке. Вам нужно только один раз приостановить его, а затем вам нужно изучить код в стеке. Сделайте паузу несколько раз, если хотите убедиться, что нашли его.

Предположим, код занимает вдвое больше времени, чем необходимо. Это означает, что когда вы ставите его на паузу, с вероятностью 50% вы увидите, что он выполняет ненужные действия. Если вы остановите его и посмотрите 10 раз, вы поймаете его в действии примерно 5 раз. Фактически, как только вы видите, что он делает что-то, что вы можете оптимизировать всего на двух образцах, вы обнаруживаете "узкое место". Исправьте это, измерьте ускорение, покажите это и повторите.

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

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

Ответ 2 · рейтинг 13 · conscho

Чтобы по-настоящему вникнуть в свой код, попробуйте stackprof.

Вот быстрое решение, как его использовать: Установите драгоценный камень: gem install stackprof. В вашем коде добавьте: require 'stackprof' и окружите часть, которую вы хотите проверить, следующим образом:

StackProf.run(mode: :cpu, out: 'stackprof-output.dump') do {YOUR_CODE} end

После запуска вашего ruby-скрипта проверьте вывод в терминале с помощью stackprof stackprof.dump:

Mode: cpu(1000)
Samples: 9145 (1.25% miss rate)
GC: 448 (4.90%)

 TOTAL    (pct)     SAMPLES    (pct)     FRAME
   236   (2.6%)         231   (2.5%)     String#blank?
   546   (6.0%)         216   (2.4%)     ActiveRecord::ConnectionAdapters::Mysql2Adapter#select
   212   (2.3%)         199   (2.2%)     Mysql2::Client#query_with_timing
   190   (2.1%)         155   (1.7%)     ERB::Util#html_escape``

Здесь вы можете увидеть все свои методы, которые требуют много времени. А теперь самое интересное: для детализации просто сделайте stackprof stackprof.dump --method String#blank?, и вы получите результат для конкретного метода:

String#blank? (lib/active_support/core_ext/object/blank.rb:80)
  samples:   231 self (2.5%)  /    236 total (2.6%)
  callers:
    112  (   47.5%)  Object#present?
  code:
                                  |    80  |   def blank?
  187    (2.0%) /   187   (2.0%)  |    81  |     self !~ /[^[:space:]]/
                                  |    82  |   end

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

Если вы хотите получить визуальный результат, сделайте stackprof stackprof.dump --graphviz >> stackprof.dot и с помощью graphviz (brew install graphviz) dot -T pdf -o stackprof.pdf stackprof.dot получите красивый PDF-файл, в котором выделены методы, выполнение которых требует длительного времени.

Ответ 3 · рейтинг 3 · ehsanul

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

http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler

Фламеграфы делают источник проблем с производительностью на удивление очевидным по сравнению с просмотром трассировки.

Ответ 4 · рейтинг 3 · Throw Away Account

Также есть ruby -rprofile или что-то подобное из исходного кода Ruby, require 'profile'

Документация:

https://ruby-doc.org/stdlib-2.1.0/libdoc/profiler/rdoc/Profiler__.html

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы