J'étudie différentes techniques d'optimisation, et je suis tombé sur ce post Analyzing Code for Efficiency? par quelqu'un qui pense que l'échantillonnage de la pile d'appels est plus efficace que l'utilisation d'un profileur. L'idée de base est que si vous regardez la pile d'appels, vous voyez où votre application est la plus susceptible de passer la plupart de son temps, puis vous y optimisez.
C'est certainement intéressant, et il est évidemment un expert en la matière, mais je ne sais pas comment afficher la pile d'appels dans Ruby. Dans le débogueur, je peux dire "pile d'informations" mais ne semble montrer qu'une seule ligne.
EDIT: J'ai vu ce commentaire de Mike Dunlavey: "Je voudrais juste souligner que si vous exécutez sous le débogueur, interrompez-le manuellement et affichez la pile des appels ..."
Je ne sais pas comment l'interrompre manuellement et afficher la pile d'appels.
Mettez juste
puts caller
n'importe où dans le code. Si vous n'aimez pas son format, c'est un tableau de chaînes, vous pouvez donc faire quelques manipulations regex pour une sortie souhaitée.
Que diriez-vous d'envoyer un signal au processus Ruby, et de créer un gestionnaire pour le signal qui vide toutes les piles?
De http://le-huy.blogspot.com/2012/04/dump-backtrace-of-all-threads-in-Ruby.html nous avons cet exemple:
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
Ensuite, nous devons envoyer le signal au processus approprié:
ps afxw | grep Ruby
kill -29 <pid>
ls -l /tmp/Ruby*
vi /tmp/Ruby_backtrace_...
Répétez le signal au moment d'échantillonnage approprié.
Vous pouvez lever une exception à tout moment, puis regarder le $@
variable prédéfinie, qui renvoie un tableau de données de suivi. Par exemple. mettez ceci dans foo.rb:
begin
raise 'foo'
rescue
puts $@
end
Exécutez-le ensuite:
$ Ruby foo.rb
foo.rb:2:in `<main>'