使用GCC进行性能分析:获取共享库中函数的调用计数

时间:2011-02-28 12:20:15

标签: c++ gcc profiling shared

我希望能够计算在库中调用函数的次数。我有可用的库的C ++源代码,但我没有使用它的可执行文件的源代码。 Gprof 接缝是一种流行的工具,但它仅适用于可执行文件。我发现sprof的信息非常有限,当编译库并使用“-g”选项链接时,它应该解析在执行期间收集的配置文件数据。很遗憾, sprof 无法打开生成的配置文件。我几乎放弃了尝试使用 sprof ,因为它接触它是很久以前写的东西而且不是很好。

问题是,如果您知道任何与GCC一起使用的工具,可以计算通话次数吗?

5 个答案:

答案 0 :(得分:3)

GCC在最近的版本中有一个编译器开关-finstrument-functions,可用于在编译代码中自动生成跟踪点挂钩。请参阅手册中的GCC Code Generation Options。有了它,你甚至不需要一个完整的拦截器,只需要一小部分功能:

  • __cyg_profile_func_enter()
  • __cyg_profile_func_exit()

在进入/退出时自动调用使用-finstrument-functions选项编译的每一段代码 您只需链接一个存根库,在这种方式下,只需返回),在正常使用时,只需要通过LD_PRELOAD通过{{1}}进行实际记录调用。

请注意,传递给这些跟踪站点挂钩的参数是被调用函数和调用者的地址;要提供名称,您必须通过符号表查找来提供它们,最好在外部跟踪本身。

示例代码(只是一个快速的谷歌,真的):hereherehere

答案 1 :(得分:1)

您应该可以使用ltrace执行此操作,使用ltrace -c -l yourlibrary运行程序,或删除-l以获取所有动态库调用的计数。

答案 2 :(得分:0)

您可以通过LD_PRELOAD库轻松完成此操作。您编写了一个库,用于捕获您正在检测的函数的调用,递增计数器,然后调用原始实现(通过调低共享对象并调用它)。然后在启动可执行文件时LD_PRELOAD你的拦截器库,让它在_exit(或SIGUSR1,或者每当)发出它的计数。

除了动态库加载器之外,它在没有任何软件支持的情况下工作,并且即使在源不可用的情况下也是间接库调用的常用技术。

答案 3 :(得分:0)

如果它是一个动态库(DLL),你只需重新编译它就可以计算并打印出一个数字,只要函数被调用为文件或网络,该数字就会递增

答案 4 :(得分:0)

您可以使用systemtap来获取函数调用次数。它是一个功能强大的工具,允许您在运行时检测任何应用程序,而无需重新编译它,只需要调试符号。

这是一个脚本,它计算函数的调用次数及其执行时间(以纳秒为单位):

# call-counts.stp

global calls, times

probe process(@1).function(@2) {
    times[probefunc()] = gettimeofday_ns()
}

probe process(@1).function(@2).return {
    now = gettimeofday_ns()
    delta = now - times[probefunc()]
    calls[probefunc()] <<< delta
}

以下是运行getenv()时如何使用它来计算/lib64/libc-2.12.2.so中对ls -1的调用:

$ sudo stap -c "ls -1" ~/tmp/count-calls.stp /lib64/libc-2.12.2.so getenv
binned_market_data
count-calls.stp
count-calls.stp~
Makefile
md
nohup.out
calls["getenv"] @count=23 @min=4841 @max=19257 @sum=142529 @avg=6196

另一个看到“str *”函数调用的例子:

$ sudo stap -c "ls -1" ~/tmp/count-calls.stp /lib64/libc-2.12.2.so "str*"
binned_market_data
count-calls.stp
count-calls.stp~
Makefile
md
nohup.out
calls["__strdup"] @count=14 @min=5035 @max=10664 @sum=80479 @avg=5748
calls["strcoll"] @count=11 @min=11626 @max=20018 @sum=140851 @avg=12804
calls["__strcoll_l"] @count=11 @min=4992 @max=9393 @sum=63179 @avg=5743
calls["strstr_ifunc"] @count=2 @min=4902 @max=7429 @sum=12331 @avg=6165