在 Unix 中的 C 中分析每个函数的内存使用情况
Profile per-function memory usage in C in Unix
在 Unix 中,有什么方法可以获得用 C 编写的程序的每个函数的总内存使用量?也就是说,包括在该函数中声明的局部变量(堆栈)、malloc 变量(堆)和静态变量(bss 和数据)。
我知道 Valgrind 的 Massif 可以检索堆上的信息,但其他两个呢?
正如 OP 强调的那样,每个 class 存储空间都可以使用不同的工具进行测量。在 old
天 (C90),这相对简单。如今,复杂得多...
静态内存:
静态内存(静态或全局),可以使用 size
工具在目标文件级别 (.o) 测量。这将包括文件中所有静态数据的内存——可能是多个函数。例如o5中的函数需要120+512 (data+bss)
size o5.o
text data bss dec hex filename
757 512 120 1389 56d o5.o
自动变量
测量自动变量 ("local") 比较棘手。在 C99 之前,分配在编译时固定(除了 now alloca
调用)。可以检查程序集生成的代码以找出为函数分配了多少堆栈 space。对于允许 VLA 的 C99,这不再可能,例如
void f(int n) {
int a[n+3] ; // Variable Length Array, size calculated at run time.
}
此外,通过优化,许多编译器能够检测到两个变量可以共享相同的 space,因为它们不会同时使用。例如,大多数编译器可以判断 x 和 y 可以共享相同的 space.
void f(int n) {
for (int i=0 ; ... ; ... ) {
int x[30] ;
} ;
for (int j=0 ; ... ; ... ) {
int y[30] ;
} ;
}
理论上,可以在 运行 时间内对堆栈大小进行采样,并尝试用 VLA 确定 'typical' 函数的大小。对于没有 VLA 的函数,通常可以从生成的程序集中提取数据。里程会有所不同。
动态变量
对于动态内存分配(malloc 和朋友)- 运行时间工具最好设置为捕获分配了多少内存。然而,大多数工具将无法测量实际的动态使用情况 - 它们通常会在特定时间点对堆进行分析,这可能比函数实际使用的更多或更少。
在 Unix 中,有什么方法可以获得用 C 编写的程序的每个函数的总内存使用量?也就是说,包括在该函数中声明的局部变量(堆栈)、malloc 变量(堆)和静态变量(bss 和数据)。
我知道 Valgrind 的 Massif 可以检索堆上的信息,但其他两个呢?
正如 OP 强调的那样,每个 class 存储空间都可以使用不同的工具进行测量。在 old
天 (C90),这相对简单。如今,复杂得多...
静态内存:
静态内存(静态或全局),可以使用 size
工具在目标文件级别 (.o) 测量。这将包括文件中所有静态数据的内存——可能是多个函数。例如o5中的函数需要120+512 (data+bss)
size o5.o
text data bss dec hex filename
757 512 120 1389 56d o5.o
自动变量
测量自动变量 ("local") 比较棘手。在 C99 之前,分配在编译时固定(除了 now alloca
调用)。可以检查程序集生成的代码以找出为函数分配了多少堆栈 space。对于允许 VLA 的 C99,这不再可能,例如
void f(int n) {
int a[n+3] ; // Variable Length Array, size calculated at run time.
}
此外,通过优化,许多编译器能够检测到两个变量可以共享相同的 space,因为它们不会同时使用。例如,大多数编译器可以判断 x 和 y 可以共享相同的 space.
void f(int n) {
for (int i=0 ; ... ; ... ) {
int x[30] ;
} ;
for (int j=0 ; ... ; ... ) {
int y[30] ;
} ;
}
理论上,可以在 运行 时间内对堆栈大小进行采样,并尝试用 VLA 确定 'typical' 函数的大小。对于没有 VLA 的函数,通常可以从生成的程序集中提取数据。里程会有所不同。
动态变量
对于动态内存分配(malloc 和朋友)- 运行时间工具最好设置为捕获分配了多少内存。然而,大多数工具将无法测量实际的动态使用情况 - 它们通常会在特定时间点对堆进行分析,这可能比函数实际使用的更多或更少。