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

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

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

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


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


Ответы (4)


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

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

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

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

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

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

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

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

person Mike Dunlavey    schedule 03.11.2010
comment
Спасибо за это, попробую этот способ. Я только что нашел perftools, который является профилировщиком выборки и создает графики вызовов, подобные следующему: perftools-rb.rubyforge.org/examples/rubygems.gif. Считаете ли вы, что выполнение этого вручную для получения дополнительной информации действительно дает большое преимущество? - person ehsanul; 04.11.2010
comment
@ehsanul: Совершенно верно, как описано в пункте 3 ссылки "Альтернативы Gprof". Но не верьте мне на слово: stackoverflow.com/questions/2624667/ stackoverflow.com/questions/2473666/ Это похоже на сравнение яркой машины с уродливым самолетом. Один выглядит красиво, но другой помогает. - person Mike Dunlavey; 04.11.2010
comment
@MikeDunlavey: вопрос новичка: как прервать работу приложения Ruby и получить трассировку? Можете ли вы захватить SIGINT, чтобы попасть в отладчик Ruby? Или все делаешь под gdb? - person fearless_fool; 07.03.2013
comment
@fearless: Этот пост говорит, что нужно поймать прерывание. - person Mike Dunlavey; 07.03.2013
comment
@MikeDunlavey: у меня не сработало - см. stackoverflow.com/questions/15278134/ - person fearless_fool; 07.03.2013

Чтобы по-настоящему вникнуть в свой код, попробуйте 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-файл, в котором выделены методы, выполнение которых требует длительного времени.

person conscho    schedule 29.06.2015

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

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

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

person ehsanul    schedule 25.01.2014
comment
Я признаю, что смотреть на следы утомительно и некрасиво, и графики пламени привлекательны, но обратные следы обнаружат надмножество ускорений по сравнению с графиками пламени. Вот почему. - person Mike Dunlavey; 30.06.2015

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

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

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

person Throw Away Account    schedule 12.07.2017