2010-11-03 8 views
19

Además de Ruby-prof y la clase principal de Benchmark, ¿qué utilizas para perfilar tu código Ruby? En particular, ¿cómo encuentras los cuellos de botella en tu código? Casi siento que necesito trabajar en mi pequeña herramienta solo para descubrir dónde se está gastando todo mi tiempo en mi código.Profiling Ruby Code

Me doy cuenta que Ruby-prof proporciona esto, pero la salida es francamente muy confusa y no hace que sea fácil averiguar qué bloques reales de tu propio código son el origen del problema (te dice qué método llama tomó la mayor parte del tiempo). Así que no estoy sacando todo lo que quisiera y realmente no he podido usarlo.

¿Quizás lo estoy haciendo mal? ¿Hay alternativas? Las búsquedas de Google no me muestran nada.

+1

¿Está teniendo los mismos problemas que tenía en [¿Es posible ignorar los métodos irrelevantes al perfilar ruby applications?] (http://stackoverflow.com/questions/2241491/is-it-possible-to-ignore-irrelevant-methods-when-profiling-ruby-applications). Descubrí la opción de eliminación del método de ruby-prof. –

Respuesta

6

Muchos de los perfiladores son así. Lo que necesita saber no es donde el programa pasa su tiempo, pero por qué. Any references on Dynamic Code Analysis?

AÑADIDOS: Here's how Encuentro "cuellos de botella" en mi código. (Odio esa palabra.) Here's a list de razones por las cuales.

Es perfectamente natural suponer que para encontrar "cuellos de botella" de alguna manera debe medir mucho. Es tan natural que casi todos los perfiladores se basan en él.

En realidad, encontrar y medir no es el mismo problema. La medición es necesaria para ver si lo que encontraste (y lo reparaste) marcó la diferencia. Encontrar lo que hay que arreglar, para mí, es más como depurar que medir.

La forma más simple de explicarlo es comenzar desde un ciclo infinito o casi infinito. ¿Cómo lo encuentras? Pausa y mira la pila, ¿verdad? porque sabes que el problema está en algún lugar de la pila. Solo necesita detenerlo una vez, y luego debe estudiar el código en la pila. Pausa algunas veces si quieres estar seguro de haberlo encontrado.

Supongamos que el código solo tarda el doble de tiempo que el necesario. Eso significa que cuando lo detenga, hay un 50% de posibilidades de que lo vea haciendo algo innecesario. Si lo pausa y lo mira 10 veces, lo captará en el acto aproximadamente 5 veces. De hecho, tan pronto como lo veas haciendo algo que puedes optimizar en tan solo 2 muestras, has encontrado un "cuello de botella". Solucionarlo, medir la aceleración, mostrarlo y repetir.

Incluso si su mayor problema no es muy grande, este método finalmente lo encontrará. Además, hay un fenómeno de ampliación, donde los pequeños problemas se vuelven más fáciles de encontrar después de eliminar los más grandes. Eso te permite seguir hasta que el código sea casi óptimo.

P.S. Después de haber hecho esto, aún puede haber oportunidades para acelerar. Por ejemplo, los algoritmos de optimización pueden depender de la estabilidad numérica. Las arquitecturas basadas en mensajes pueden dificultar el rastreo del código que se está ejecutando. En el software en tiempo real, un problema de rendimiento solo puede ocurrir ocasionalmente y ser menos fácil de muestrear. Esto requiere más inteligencia. Volver a simplemente medir no lo hace.

+1

Gracias por eso, probaré este método. También encontré perftools, que es un generador de perfiles de muestreo, y produce gráficos de llamadas como los siguientes: http://perftools-rb.rubyforge.org/examples/rubygems.gif - ¿Crees que hacerlo manualmente por el poco de información adicional? proporciona mucha ventaja en realidad? – ehsanul

+0

@ehsanul: Absolutamente, como se explica en el punto 3 del enlace Alternativas a Gprof. Pero no confíe en mi palabra: http://stackoverflow.com/questions/2624667/whats-a-very-easy-c-profiler-vc/2624725#2624725 http://stackoverflow.com/questions/ 2473666/tips-for-optimizing-c-net-programs/2474118 # 2474118 Es como comparar un coche llamativo con un avión feo. Uno se ve bien, pero el otro te lleva allí. –

+0

@MikeDunlavey: la pregunta de un tirómano: ¿cómo se interrumpe una aplicación de ruby ​​y se rastrea? ¿Puedes capturar SIGINT para entrar en el depurador Ruby? ¿O haces todo bajo gdb? –

2

Ésta es mi propia pregunta, pero he encontrado una herramienta que es tan increíble para el perfil que tengo que añadir aquí:

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

Flamegraphs hacen que la fuente de los problemas de rendimiento increíblemente obvia, relativa a mirar atrás.

+1

Admito que mirar los backtraces es tedioso y feo, y los gráficos de llama son sexys, pero el las trazas inversas encontrarán un superconjunto de aceleraciones, en comparación con los gráficos de llamas. [* Aquí está el por qué. *] (Http://stackoverflow.com/a/27867426/23771) –

5

Para perforar realmente en su código, pruebe stackprof.

Aquí hay una solución rápida sobre cómo usarlo: Instale la gema: gem install stackprof. En su código de añadir: require 'stackprof' y rodear la parte que desea comprobar con esto:

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

Después de ejecutar la secuencia de comandos de rubí vaya a ver la salida de la terminal con 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`` 

Aquí puedes ver todos tus métodos que requieren mucho tiempo. Ahora la parte impresionante: Para perforar en tan sólo hacer stackprof stackprof.dump --method String#blank? y se obtiene la salida para el método específico:

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 

Y usted puede fácilmente averiguar qué parte de su código necesita mucho tiempo para correr.

Si desea obtener una salida visual hacen stackprof stackprof.dump --graphviz >> stackprof.dot y el uso de graphviz (brew install graphviz) dot- T pdf -o stackprof.pdf stackprof.dot obtener una hermosa salida PDF, lo que pone de relieve los métodos que tardan mucho tiempo en ejecutarse.