2009-09-24 10 views
5

Digamos que tengo una función que se llama MUCHO en muchos lugares diferentes. Entonces me gustaría saber quién llama más a estas funciones. Por ejemplo, las 5 personas que llaman o que llaman a esta función más de N veces.¿Hay alguna manera de descubrir las principales llamadas de una función C?

Estoy usando AS3 Linux, gcc 3.4.

Por ahora sólo hay que poner un punto de interrupción y luego se detiene allí después de cada 300 veces, por lo que fuerza bruta ...

¿Alguien sabe de herramientas que me puedan ayudar?

Gracias

+1

¿No puedes hacer esto? –

+2

No lo sé, ¿verdad? – vehomzzz

+1

nunca usado gprof – vehomzzz

Respuesta

2

Escribí el ejemplo de registro de llamadas solo por diversión. Una macro cambia la llamada de función con una instrumentada.

include <stdio.h>. 

int funcA(int a, int b){ return a+b; } 

// instrumentation 

void call_log(const char*file,const char*function,const int line,const char*args){ 
    printf("file:%s line: %i function: %s args: %s\n",file,line,function,args); 
} 

#define funcA(...) \ 
    (call_log(__FILE__, __FUNCTION__, __LINE__, "" #__VA_ARGS__), funcA(__VA_ARGS__)). 

// testing 

void funcB(void){ 
    funcA(7,8); 
} 


int main(void){ 
    int x = funcA(1,2)+ 

      funcA(3,4); 

    printf("x: %i (==10)\n", x); 

    funcA(5,6); 

    funcB(); 
} 

Salida:

file:main.c line: 22 function: main args: 1,2 
file:main.c line: 24 function: main args: 3,4 
x: 10 (==10) 
file:main.c line: 28 function: main args: 5,6 
file:main.c line: 17 function: funcB args: 7,8 
+0

¡¡¡Genial !!!! Podría implementar algo así – vehomzzz

2

Perfil ayuda.

+0

Estoy utilizando un perfil oprofile, pero no me da este nivel de información – vehomzzz

+0

Hay muchos que lo hacen. Danadam ha sugerido uno en su respuesta. –

18

Compila con la opción -pg, ejecuta el programa por un tiempo y luego usa gprof. La ejecución de un programa compilado con la opción -pg generará el archivo gmon.out con el perfil de ejecución. gprof puede leer este archivo y presentarlo en forma legible.

+3

Y gprof2dot (http://code.google.com/p/jrfonseca/wiki/Gprof2Dot) puede hacer que la salida en un buen gráfico ;-) – ChristopheD

1

Como mencionaste oprofile en otro comentario, diré que oprofile admite generar callgraphs en programas perfilados.

Consulte http://oprofile.sourceforge.net/doc/opreport.html#opreport-callgraph para obtener más información.

Vale la pena señalar que esto definitivamente no es tan claro como el perfil de llamadores que puede obtener de gprof u otro generador de perfiles, ya que los números que informa es el número de veces que oprofile recogió una muestra en la que X llama a una función determinada , no la cantidad de veces que X llamó una función dada. Pero esto debería ser suficiente para descubrir las principales llamadas de una función determinada.

0

Además del analizador gprof mencionado anteriormente, también puede probar la herramienta de cobertura de código gcov. La información sobre la compilación y el uso de ambos debe incluirse en el manual de gcc.

1

Un método algo engorroso, pero que no requiere herramientas adicionales:

#define COUNTED_CALL(fn, ...) do{ \ 
    fprintf(call_log_fp, "%s->%s\n", __FUNCTION__, #fn) ; \ 
    (fn)(__VA_ARGS__) ; \ 
}while(0) ; 

A continuación, todas las llamadas escritas como:

int input_available = COUNTED_CALL(scanf, "%s", &instring) ; 

se registrará en el archivo asociado a call_log_fp (un archivo * global que debes haber inicializado). El registro de lo anterior se vería así:

main->scanf 

A continuación, puede procesar ese archivo de registro para extraer los datos que necesita. Incluso podría escribir su propio código para hacer la instrumentación que lo haría tal vez menos engorroso.

Sin embargo, podría ser un poco ambiguo para las funciones miembro de la clase C++. No estoy seguro de si hay una macro __CLASS__.

0

Una vez más, stack sampling to the rescue! Solo toma un montón de "Stackshots", tantas como quieras. Deseche cualquier muestra donde su función (llámala F) no esté en algún lugar de la pila.(Si está descartando la mayoría de ellos, entonces F no es un problema de rendimiento.)

En cada muestra restante, ubique la llamada en F y vea qué función (llámala G) esa llamada está activada. Si F es recursivo (aparece más de una vez en la muestra) solo usa la llamada más alta.

clasificar su Gs por el número de pilas aparece en cada una.

Si no quieres hacer esto a mano, se puede hacer una sencilla herramienta o script. No necesitas un trillón de muestras. 20 o más le darán información razonablemente buena.

Por cierto,, si lo que realmente está tratando de hacer es encontrar problemas de rendimiento, en realidad no necesita hacer todo ese descarte y clasificación. De hecho, no descartes las ubicaciones exactas de la instrucción de llamada dentro de cada G. Esos datos pueden darte un poco más que el hecho de que estaban en algún lugar dentro de G.

P.S. Todo esto se basa en la suposición de que cuando dice "lo llama más" quiere decir "gasta la mayor cantidad de tiempo de reloj de pared en llamarlo", no "lo llama el mayor número de veces". Si está interesado en el rendimiento, la fracción del tiempo del reloj de pared es más útil que el conteo de llamadas.

Cuestiones relacionadas