2011-02-08 15 views
8

La salida de un generador de perfiles típico es una lista de funciones en su código, ordenadas por la cantidad de tiempo que cada función tomó mientras se ejecutaba el programa.Programa de creación de perfiles por tipo de actividad

Esto es muy bueno, pero a veces me interesa más lo que estaba haciendo el programa la mayor parte del tiempo, que con dónde estaba EIP la mayor parte del tiempo.

Un ejemplo de salida de mi perfilador hipotético es:

Waiting for file IO - 19% of execution time. 
Waiting for network - 4% of execution time 
Cache misses  - 70% of execution time. 
Actual computation - 7% of execution time. 

¿Hay un generador de perfiles tales? ¿Es posible derivar tal salida de un perfilador "estándar"?

Estoy usando Linux, pero estaré encantado de escuchar cualquier solución para otros sistemas.

+0

¿Hay herramientas para tomar datos de perfil y ponerlos de esta forma? –

+0

¿En qué sistema operativo quiere ejecutar esto? Parece que existen tales herramientas para Solaris y Mac OS X. –

+1

Kudos para elegir porcentajes de ejemplo que suman 100% :-) – templatetypedef

Respuesta

1

Esto es solo Solaris, pero dtrace puede monitorear casi todo tipo de E/S, CPU con conexión/desconexión, tiempo en funciones específicas, tiempo de inactividad, etc. No estoy seguro de si puede determinar errores de caché, suponiendo te refieres a la memoria caché de la CPU: no estoy seguro de si esa información está disponible o no por la CPU.

+0

También los instrumentos para Mac OS X pueden hacer esto, creo que incluso puede estar basado en DTrace. –

1

Por favor, eche un vistazo a at this y this.

Considera cualquier hilo. En cualquier momento, está haciendo algo, y lo está haciendo por una razón, y la lentitud se puede definir como el tiempo que se gasta por razones pobres: no es necesario que dedique ese tiempo.

Tome una instantánea del hilo en un punto en el tiempo. Tal vez se trata de un error de caché, en una instrucción, en una declaración, en una función, llamada desde una instrucción de llamada en otra función, llamada desde otra, y así sucesivamente, hasta call _main. Cada uno de esos pasos tiene una razón, que revela un examen del código.

  1. Si alguno de esos pasos no es una buena razón y podría evitarse, ese instante de tiempo no necesita ser gastado.

Tal vez en ese momento el disco está llegando a cierto sector, por lo que se puede iniciar la transmisión de datos para llenar un búfer para que se pueda cumplir una instrucción de lectura en una función y esa función llamado desde un sitio de llamada en otra función, y desde otro, y así sucesivamente, hasta call _main, o lo que sea que sea la parte superior del hilo.

  1. Repetir punto anterior 1.

Por lo tanto, el camino para encontrar los cuellos de botella es encontrar cuando el código es pasar el tiempo por razones pobres, y la mejor manera de descubrir que es para tomar instantáneas de su estado. El EIP, o cualquier otra parte pequeña del estado, no va a hacerlo, porque no le dirá por qué.

Muy pocos perfiladores "lo consiguen". Los que sí lo hacen son los muestreadores de pila del reloj de pared que informan por línea de código (no por función) porcentaje de tiempo activo (no cantidad de tiempo, especialmente no como tiempo "propio" o "exclusivo"). eso es Zoom, y hay otros.

Ver dónde se cuelga el EIP es como intentar decir la hora en un reloj con solo una segunda mano. Medir funciones es como intentar decir la hora en un reloj con algunos de los dígitos faltantes.Perfilar solo durante el tiempo de CPU, no durante el tiempo bloqueado, es como intentar decir la hora en un reloj que deja de funcionar aleatoriamente durante largos periodos. Preocuparse por la precisión de la medición es como tratar de programar su hora de almuerzo a la segunda.

Esto no es un tema misterioso.

+0

Presentó el método estadístico clásico de muestreo, y anote que puede obtener resultados más precisos muestreando uniformemente al azar, lo cual es mejor que muestrear solo cuando se llama a una función, como lo hace 'gprof'. Como nota al margen, comentaré que no estoy seguro de que en este caso el muestreo brinde una ventaja uniforme, ya que de todas maneras está sobremuestreando, el muestreo en cada llamada a la función es más que suficiente. Por supuesto, obtendrá resultados peores, pero su generador de perfiles será más simple y tal vez eso lo valga. Pero lo que no entiendo es, ¿cómo responde eso mi pregunta? –

+0

@Elazar: Creo que una respuesta válida a una pregunta es cuestionar la premisa (legalmente :-). La premisa era que para saber lo que un programa está haciendo la mayor parte del tiempo, ciertos resultados específicos son útiles, y eso es lo que cuestiono. En cuanto al método, no hay un método clásico. El muestreo cuando se llaman los métodos no es un muestreo. (Se llama instrumentación.) El muestreo no debe correlacionarse con el estado del programa, ya que si está correlacionado, puede pasar por alto problemas grandes (como perder todo el IO, como puede ver con gprof y el generador de perfiles VS). Muestra la pila, al azar. –

+0

Mike, me refiero al muestreo como en las estadísticas. Mide el estado del programa en algún momento. La instrumentación es solo una forma de probar su programa de forma no uniforme, este http://goo.gl/3mSJ0 es otra forma no estándar de samplearlo. Lo que estoy diciendo es que, aunque la instrumentación no muestrea de manera uniforme, muestrea su programa con la frecuencia suficiente para que efectivamente tenga una muestra cada, digamos, 2 ms, y por lo tanto también puede ser lo suficientemente útil. Sabrá qué trozos de código son el cuello de botella a su tasa de muestreo efectiva. El muestreo uniforme es mejor, pero el muestreo no uniforme no es inútil. –

Cuestiones relacionadas