记录一个demo模拟googleperf的调用栈统计 📅 2026/6/25 13:04:49 上代码///////////////////////////#include stdio.h #include stdlib.h #include signal.h #include sys/time.h #include unistd.h #include execinfo.h #define MAX_STACK_DEPTH 16 volatile int sample_count 0; void collect_call_stack() { void* buffer[MAX_STACK_DEPTH]; int depth backtrace(buffer, MAX_STACK_DEPTH); printf(\n[采样 #%d] 调用栈深度: %d\n, sample_count, depth); // 关键修改用 backtrace_symbols 解析成可读的符号 char** symbols backtrace_symbols(buffer, depth); if (symbols) { for (int i 0; i depth i 8; i) { printf( %s\n, symbols[i]); } if (depth 8) { printf( ... 还有 %d 帧\n, depth - 8); } free(symbols); // 别忘了释放 } } void profiling_handler(int sig) { collect_call_stack(); } void function_c() { for (volatile long i 0; i 100000000; i); } void function_b() { for (int i 0; i 3; i) { function_c(); } } void function_a() { for (int i 0; i 3; i) { function_b(); } } int main() { signal(SIGPROF, profiling_handler); struct itimerval timer; timer.it_value.tv_sec 0; timer.it_value.tv_usec 10000; timer.it_interval.tv_sec 0; timer.it_interval.tv_usec 10000; if (setitimer(ITIMER_PROF, timer, NULL) -1) { perror(setitimer 失败); return 1; } printf( 性能采样器已启动 (每10ms CPU时间采样一次) \n); printf(程序正在执行计算采样器会周期性记录调用栈...\n\n); function_a(); printf(\n 采样完成 \n); printf(总共采集了 %d 个样本\n, sample_count); return 0; }编译g b.cpp -rdynamic./a.outubuntu22NYX:~/test$ ./a.out 性能采样器已启动 (每10ms CPU时间采样一次) 程序正在执行计算采样器会周期性记录调用栈... [采样 #1] 调用栈深度: 10 ./a.out(_Z18collect_call_stackv0x32) [0x62c8211fe27b] ./a.out(_Z17profiling_handleri0x14) [0x62c8211fe398] /lib/x86_64-linux-gnu/libc.so.6(0x42520) [0x7984c7c42520] ./a.out(_Z10function_cv0x2b) [0x62c8211fe3c6] ./a.out(_Z10function_bv0x1a) [0x62c8211fe3e8] ./a.out(_Z10function_av0x1a) [0x62c8211fe410] ./a.out(main0xa8) [0x62c8211fe4c6] /lib/x86_64-linux-gnu/libc.so.6(0x29d90) [0x7984c7c29d90] ... 还有 2 帧