Подтвердить что ты не робот

Как вы просматриваете образец стека вызовов в рубине?

Я изучаю различные методы оптимизации, и я столкнулся с этим сообщением Анализ кода для эффективности? тем, кто считает, что выборка стека вызовов более эффективна, чем использование профилировщик. Основная идея заключается в том, что если вы посмотрите на стек вызовов, вы увидите, где ваше приложение, скорее всего, будет тратить большую часть своего времени, а затем оптимизировать его.

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

EDIT: Я видел этот комментарий Майка Данлави: "Я хотел бы отметить, что если вы запустите под отладчиком, прервите его вручную и отобразите стек вызовов..."

Я просто не уверен, как прервать его вручную и отключить стек вызовов.

4b9b3361

Ответ 1

Просто поместите

puts caller

в любом месте кода. Если вам не нравится его формат, это массив строк, поэтому вы можете выполнять некоторую манипуляцию с регулярным выражением для желаемого вывода.

Ответ 2

Вы можете в любое время исключить исключение, а затем просмотреть предопределенную переменную [email protected], которая возвращает массив данных backtrace. Например. поместите это в foo.rb:

begin                                                                        
  raise 'foo'                                                                
rescue                                                                       
  puts [email protected]                                                                    
end  

Затем запустите его:

$ ruby foo.rb 
foo.rb:2:in `<main>'

Ответ 3

Как насчет отправки сигнала в рубиновый процесс и создания обработчика сигнала, который сбрасывает все стеки?

Из http://le-huy.blogspot.com/2012/04/dump-backtrace-of-all-threads-in-ruby.html у нас есть этот пример:

require 'pp'

def backtrace_for_all_threads(signame)
  File.open("/tmp/ruby_backtrace_#{Process.pid}.txt","a") do |f|
      f.puts "--- got signal #{signame}, dump backtrace for all threads at #{Time.now}"
      if Thread.current.respond_to?(:backtrace)
        Thread.list.each do |t|
          f.puts t.inspect
          PP.pp(t.backtrace.delete_if {|frame| frame =~ /^#{File.expand_path(__FILE__)}/},
               f) # remove frames resulting from calling this method
        end
      else
          PP.pp(caller.delete_if {|frame| frame =~ /^#{File.expand_path(__FILE__)}/},
               f) # remove frames resulting from calling this method
      end
  end
end

Signal.trap(29) do
  backtrace_for_all_threads("INFO")
end

Затем нам нужно отправить сигнал в соответствующий процесс:

ps afxw | grep ruby
kill -29 <pid>
ls -l /tmp/ruby*
vi /tmp/ruby_backtrace_...

Повторите сигнал при соответствующем времени выборки.