CPU调用火焰图

分析C++程序的CPU调用并生成火焰图(Flame Graph)是性能分析中常用的方法,可以直观地展示程序的函数调用栈及其CPU占用情况。以下是详细的步骤,介绍如何在Linux环境下分析C++程序的CPU调用并生成火焰图,特别针对你的需求(结合前文提到的valgrind背景,可能涉及守护进程等场景)。


分析C++程序CPU调用的工具

以下是常用的工具,用于捕获CPU调用并生成火焰图:

推荐使用 perfFlameGraph,因为它们轻量、灵活,且生成的结果直观,适合分析复杂C++程序的CPU调用。


准备工作

安装必要工具

在Linux系统上安装以下工具:

# Ubuntu/Debian
sudo apt-get update
sudo apt-get install perf linux-tools-common linux-tools-$(uname -r) git

# CentOS/RHEL
sudo yum install perf git

克隆FlameGraph工具集:

git clone https://github.com/brendangregg/FlameGraph.git
cd FlameGraph

编译C++程序

为确保调用栈信息准确,编译程序时需要启用调试符号:

g++ -g -o my_program my_program.cpp

使用 perf 捕获CPU调用数据

perf 是Linux下强大的性能分析工具,可以采样程序的调用栈并生成火焰图所需的数据。

采样运行中的程序

如果程序是普通进程:

perf record -F 99 -g -o perf.data ./my_program

采样守护进程(通过PID)

如果要分析已运行的守护进程:

  1. 找到守护进程的PID:

    ps aux | grep your_daemon
  2. 使用 perf record 附加到指定PID:

    perf record -F 99 -g -p <PID> -o perf.data

处理采样数据

perf 数据转换为调用栈格式:

perf script -i perf.data > out.perf

使用 FlameGraph 生成火焰图

FlameGraph工具集中的 stackcollapse-perf.plflamegraph.pl 脚本可以将 perf 数据转换为火焰图。

折叠调用栈

perf script 的输出转换为FlameGraph所需的格式:

./FlameGraph/stackcollapse-perf.pl out.perf > out.folded

生成火焰图

将折叠后的数据转换为SVG格式的火焰图:

./FlameGraph/flamegraph.pl out.folded > flamegraph.svg

查看火焰图


使用 valgrind --tool=callgrind 生成火焰图

如果更倾向于使用 valgrind,可以用 callgrind 工具生成调用图数据,再转换为火焰图。

运行 callgrind

valgrind --tool=callgrind ./my_program

转换为火焰图

  1. 使用 callgrind_annotatekcachegrind 查看原始数据(可选):

    kcachegrind callgrind.out.xxx
  2. 使用 callgrind2flame(第三方工具)或手动转换:

注意事项


分析火焰图

生成的火焰图(flamegraph.svg)具有以下特点:

示例分析

假设你的C++程序有一个热点函数:

#include <vector>

void hot_function() {
    std::vector<int> vec;
    for (int i = 0; i < 1000000; ++i) {
        vec.push_back(i); // CPU密集操作
    }
}

int main() {
    for (int i = 0; i < 10; ++i) {
        hot_function();
    }
    return 0;
}
  1. 编译并运行:

    g++ -g -o hot hot.cpp
    perf record -F 99 -g ./hot
    perf script > out.perf
    ./FlameGraph/stackcollapse-perf.pl out.perf > out.folded
    ./FlameGraph/flamegraph.pl out.folded > flamegraph.svg
  2. 打开 flamegraph.svg,你会看到:

  3. 优化建议:


分析守护进程的CPU调用

对于已运行的守护进程(通过PID),直接使用 perf

  1. 获取PID:

    ps aux | grep your_daemon
  2. 采样:

    perf record -F 99 -g -p <PID> -o perf.data
  3. 生成火焰图:

    perf script -i perf.data > out.perf
    ./FlameGraph/stackcollapse-perf.pl out.perf > out.folded
    ./FlameGraph/flamegraph.pl out.folded > daemon_flamegraph.svg

注意事项


其他工具


示例脚本:自动化生成火焰图

以下是一个自动化脚本,用于捕获CPU调用并生成火焰图:

<xaiArtifact artifact_id="f0802be7-eaa3-4832-bcd2-6c5e590a923e" artifact_version_id="62dd91b6-b07a-43a3-83f5-b54e241b1edb" title="generate_flamegraph.sh" contentType="text/x-shellscript">
#!/bin/bash

# 检查参数
if [ -z "$1" ]; then
    echo "Usage: $0 <program_or_pid>"
    exit 1
fi

# 检查是否为PID
if [[ "$1" =~ ^[0-9]+$ ]]; then
    CMD="perf record -F 99 -g -p $1 -o perf.data"
else
    CMD="perf record -F 99 -g $1 -o perf.data"
fi

# 运行perf
$CMD
if [ $? -ne 0 ]; then
    echo "Error running perf"
    exit 1
fi

# 转换数据
perf script -i perf.data > out.perf
./FlameGraph/stackcollapse-perf.pl out.perf > out.folded
./FlameGraph/flamegraph.pl out.folded > flamegraph.svg

echo "Flame graph generated: flamegraph.svg"
</xaiArtifact>

保存为 generate_flamegraph.sh,赋予执行权限:

chmod +x generate_flamegraph.sh

使用示例: - 分析普通程序:

./generate_flamegraph.sh ./my_program

注意事项