我想了解-pg
(或-p
)标志在用GCC编译C代码时是如何工作的。
官方GCC文档只声明:
-pg
生成额外的代码来编写适合分析程序gprof的概要信息。在编译需要数据的源文件时必须使用此选项,并且在链接时也必须使用此选项。
这真的让我很感兴趣,因为我正在做一个关于分析器的小研究。我正在为这项工作挑选最好的工具。
使用-pg编译您的代码,以便Gprof报告详细信息。参见gprof手册,9.1剖析的实现:
分析通过改变程序中每个函数的编译方式来工作,以便在调用它时,它将隐藏一些关于从何处调用它的信息。从这里,分析器可以找出是哪个函数调用了它,并可以计算它被调用了多少次。当使用
-pg
选项编译程序时,编译器会进行此更改,这会导致每个函数将调用mcount
(或_mcount
,或__mcount
,取决于操作系统和编译器)作为其第一个操作之一。包含在分析库中的
mcount
例程负责在内存中的调用图表中记录它的父例程(子例程)和它的父例程的父例程。这通常是通过检查堆栈帧来找到子节点的地址和原始父节点的返回地址来完成的。由于这是一个非常依赖于机器的操作,所以mcount
本身通常是一个简短的汇编语言存根例程,它提取所需的信息,然后用两个参数——frompc
和selfpc
调用__mcount_internal
(一个普通的C函数)。__mcount_internal
负责维护内存中的调用图,该图记录了frompc
,selfpc
以及这些调用弧线中的每个被遍历的次数。…
请注意,使用这样的分析分析器,您将分析在没有分析工具的发布中编译的相同代码。插装代码本身有一个开销。此外,检测代码可能会改变指令和数据缓存的使用。
与检测分析器相反,像Intel VTune这样的采样分析器通过使用操作系统中断定期查看目标程序的程序计数器来处理非检测代码。它还可以查询特殊的CPU寄存器,让您更深入地了解正在发生的事情。
参见profiler instrumentation Vs Sampling。
此链接简要说明了gprof的工作原理。
这个链接给出了一个广泛的批评。(查看我对存档问题的回答)
From "用trace"测量函数持续时间:
工具主要有两种窗体—显式声明的跟踪点和隐式跟踪点。
显式跟踪点由开发人员定义的类的位置声明Tracepoint,以及关于哪些数据的附加信息应该在特定的追踪地点收集。隐式的跟踪点由编译器自动放置到代码中,或者由于编译器标志,或者由于开发人员对常用宏的重新定义。
隐含地测量函数,当内核被配置为支持函数跟踪,内核构建系统将-pg添加到使用的标志中编译器。这会导致编译器将代码添加到每个函数的序言,它调用一个称为McOunt的特殊程序集例程。这个编译器选项是专门用于分析和跟踪目的。