Как лучше всего профилировать действие контроллера в Ruby on Rails. В настоящее время я использую метод перебора вызовов puts Time.now между тем, что, по моему мнению, будет узким местом. Но это действительно очень грязно. Должен быть способ получше.





Используйте стандартную библиотеку Benchmark и различные тесты, доступные в Rails (модульные, функциональные, интеграционные). Вот пример:
def test_do_something
elapsed_time = Benchmark.realtime do
100.downto(1) do |index|
# do something here
end
end
assert elapsed_time < SOME_LIMIT
end
Итак, здесь мы просто делаем что-то 100 раз, измеряем время через библиотеку Benchmark и гарантируем, что это заняло меньше времени, чем SOME_LIMIT.
Вы также можете найти эти ссылки полезными: Ссылка на Benchmark.realtime и Test :: Ссылка на модуль. Кроме того, если вам нравится «читать книги», я позаимствовал эту идею из примера из Гибкая веб-разработка с Rails, в котором рассказывается все о различных типах тестирования и немного о тестировании производительности.
Есть Railscast по профилированию, который стоит посмотреть
Вы можете попробовать сервис FiveRuns TuneUp, так как он действительно впечатляет. Отказ от ответственности: я никак не связан с FiveRuns, я только что попробовал эту услугу.
TuneUp - это бесплатная служба, с помощью которой вы загружаете плагин, и когда вы запускаете приложение, он вставляет панель в верхней части экрана, которую можно развернуть для отображения подробных показателей производительности.
Он дает вам несколько хороших графиков, в том числе тот, который показывает, какая часть времени тратится на модель, представление и контроллер. Вы даже можете детализировать данные, чтобы увидеть отдельные SQL-запросы, которые выполняет ActiveRecord, если вам нужно, и он может показать вам базовую схему базы данных еще одним щелчком мыши.
Наконец, вы можете при желании загрузить свои данные профилирования на сайт FiveRuns для анализа работы сообщества и получения рекомендаций.
Ссылка не работает (истек срок действия DNS).
Некоторое время назад я освоил эту технику, и она мне очень пригодилась.
Когда он будет установлен, вы можете добавить ?profile=true к любому URL-адресу, который попадает в контроллер. Ваше действие будет выполняться как обычно, но вместо того, чтобы доставлять обработанную страницу в браузер, он отправит подробную, красиво отформатированную страницу ruby-prof, которая показывает, где ваше действие потратило свое время.
Сначала добавьте ruby-prof в свой Gemfile, возможно, в группу разработчиков:
group :development do
gem "ruby-prof"
end
Затем добавьте вокруг фильтра в свой ApplicationController:
around_action :performance_profile if Rails.env == 'development'
def performance_profile
if params[:profile] && result = RubyProf.profile { yield }
out = StringIO.new
RubyProf::GraphHtmlPrinter.new(result).print out, :min_percent => 0
self.response_body = out.string
else
yield
end
end
Чтение вывода ruby-prof - это искусство, но я оставлю это как упражнение.
Дополнительное примечание ScottJShea: Если вы хотите изменить тип измерения, поместите это:
RubyProf.measure_mode = RubyProf::GC_TIME #example
До if в профильном методе контроллера приложений. Вы можете найти список доступных измерений на страница ruby-prof. На момент написания этой статьи потоки данных memory и allocations кажутся поврежденными (увидеть дефект).
для тех, кто не умеет вставлять это, вам также необходимо добавить «require 'ruby-prof'» в верхнюю часть вашего ApplicationController. Кроме того, мне пришлось изменить "self.response_body =" на "self.response.body =" (Rails 2.3.14)
Спасибо за эти настройки. response_body был добавлен в Rails 3.0. И если вы используете Bundler, вам не нужно требовать ruby-prof, но я рад, что этот метод можно было легко адаптировать к более старой версии Rails.
Спасибо за совет, Павлинг. Я также использую rails 2.3.14 и не могу заставить это работать. Я получаю «неправильное количество аргументов (0 для 1)» в graph_html_printer.rb: 98: в `full_name ', независимо от того, какую версию ruby-prof я устанавливаю. Есть идеи, что могло быть причиной этого?
Чтобы это переопределило формат возврата для JSON, XML и т. д., Добавьте это в оператор if: headers["Content-Type"] = "text/html"
Это работает в Rails 4.2.6:
o=OpenStruct.new(logger: Rails.logger)
o.extend ActiveSupport::Benchmarkable
o.benchmark 'name' do
# ... your code ...
end
Это не отображает ничего в журналах или где-либо еще.
Этот ответ расскажет вам, как убедиться, что ваше действие выполняется достаточно быстро. Это не поможет вам с профилированием, то есть выяснением того, какая часть действия занимает больше всего времени.