Существует ли способ выяснить главные вызывающие стороны функции C?

шутка sean.bright получила меня думающий..., почему бы не использовать...

* * * * * /my/script

... и в рамках сценария делают это...

#!/bin/bash
export WHEN=`date '+%M'`
echo $WHEN
export DOIT=`echo "$WHEN % 5" | bc` 
echo $DOIT
if [ $DOIT != 0 ] ; then
    echo "ha ha ha"
fi
echo "done"

... клудж..., возможно, но столь же ужасный как crontab... Я не знаю.

5
задан raven 24 September 2009 в 20:34
поделиться

7 ответов

Я написал пример регистрации вызовов просто для удовольствия. Макрос изменяет вызов функции на инструментальный.

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();
}

Вывод:

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
2
ответ дан 18 December 2019 в 06:35
поделиться

Скомпилируйте с параметром -pg, запустите программу на некоторое время, а затем используйте gprof. При запуске программы, скомпилированной с параметром -pg, будет создан файл gmon.out с профилем выполнения. gprof может прочитать этот файл и представить его в удобочитаемой форме.

18
ответ дан 18 December 2019 в 06:35
поделиться

Поскольку вы упомянули oprofile в другом комментарии, я скажу, что oprofile поддерживает создание графов вызовов в профилированных программах.

См. http://oprofile.sourceforge.net/doc/ opreport.html # opreport-callgraph для получения дополнительных сведений.

Стоит отметить, что это определенно не так ясно, как профиль вызывающих абонентов, который вы можете получить от gprof или другого профилировщика, поскольку числа, которые он сообщает, являются количеством раз, когда oprofile собрал образец, в котором X является вызывающим для данной функции, а не количество раз, когда X вызывает данную функцию. Но этого должно быть достаточно, чтобы выяснить, кто чаще всего вызывает данную функцию.

1
ответ дан 18 December 2019 в 06:35
поделиться

Несколько громоздкий метод, но не требующий дополнительных инструментов:

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

Затем все вызовы, записанные как:

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

, будут регистрироваться в файле, связанном с call_log_fp (глобальный ФАЙЛ *, который вы должны инициализированы). Журнал для вышеуказанного будет выглядеть так:

main->scanf

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

Однако может быть немного двусмысленным для функций-членов класса C ++. Я не уверен, существует ли макрос __CLASS__.

1
ответ дан 18 December 2019 в 06:35
поделиться

Профилирование помогает.

2
ответ дан 18 December 2019 в 06:35
поделиться

In addition to the aforementioned gprof profiler, you may also try the gcov code-coverage tool. Information on compiling for and using both should be included in the gcc manual.

0
ответ дан 18 December 2019 в 06:35
поделиться

И снова выборка стека на помощь ! Просто сделайте кучу "стекшотов", сколько хотите. Отбросьте все образцы, в которых ваша функция (назовите ее F) не находится где-то в стеке. (Если вы отбрасываете большинство из них, тогда F не является проблемой производительности.)

На каждом оставшемся образце найдите вызов F и посмотрите, в какой функции (назовите ее G) этот вызов. Если F - рекурсивный (он встречается более одного раза в образце) используйте только самый верхний вызов.

Оцените свои G по количеству стеков, в которых появляется каждый.

Если вы не хотите делать это вручную, вы можете сделать простой инструмент или скрипт. Вам не нужен миллион образцов. Примерно 20 дадут вам достаточно хорошую информацию.

Между прочим, , если вы действительно пытаетесь найти проблемы с производительностью, вы этого не сделаете. На самом деле нужно делать все это отбрасывание и ранжирование. Фактически - не отбрасывайте точное расположение инструкции вызова внутри каждого G. Это может сказать вам немного больше, чем просто факт, что они были где-то внутри G.

PS Все это основано на предположении, что когда вы говорите «называет это чаще всего», вы имеете в виду «тратит больше всего времени на вызовы настенных часов», а не «вызывает наибольшее количество раз». Если вас интересует производительность, доля времени настенных часов более полезна, чем счетчик вызовов.

Все это основано на предположении, что когда вы говорите «вызывает наибольшее количество раз», вы имеете в виду «тратит больше всего времени на вызовы настенных часов», а не «вызывает наибольшее количество раз». Если вас интересует производительность, доля времени настенных часов более полезна, чем счетчик вызовов.

Все это основано на предположении, что когда вы говорите «вызывает наибольшее количество раз», вы имеете в виду «тратит больше времени на вызовы настенных часов», а не «вызывает наибольшее количество раз». Если вас интересует производительность, доля времени настенных часов более полезна, чем счетчик вызовов.

0
ответ дан 18 December 2019 в 06:35
поделиться