You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现跨不同perf事件的差值分析?获取L2非L3停顿数据

解决方法

因为perf原生工具没有直接计算不同事件差值的功能,你可以通过导出事件数据到文本,再用脚本统计计算差值的方式实现需求,以下是三种可行的方案:

方案一:将两个事件录到同一份文件后导出计算

这种方式能避免两次录制带来的程序行为差异,结果更准确:

  1. 重新录制同时包含两个事件的性能数据:

    perf record -e cycle_activity.stalls_l2_miss,cycle_activity.stalls_l3_miss -g ./你的程序
    

    (-g用于记录调用栈,若不需要可以省略)

  2. 将事件数据导出为结构化文本:

    perf report -n --stdio -F comm,symbol,period,overhead | grep -E "(stalls_l2_miss|stalls_l3_miss|^ Symbol)" > perf_events.txt
    
    • -n显示原始事件计数(period),--stdio强制文本输出,-F指定要导出的字段
    • 过滤命令只保留目标事件和符号表头,方便后续处理
  3. 用awk脚本计算差值(示例):

    BEGIN {
        print "符号\tL2停顿计数\tL3停顿计数\t仅L2停顿计数\t仅L2占比(%)"
        print "--------------------------------------------------------"
        total_l2 = 0
    }
    # 统计总L2停顿数(用于计算精确占比)
    /stalls_l2_miss/ {
        total_l2 += $NF
    }
    # 遍历符号和对应事件
    /^ Symbol/ {
        sym = $2
    }
    /stalls_l2_miss/ {
        l2_cnt = $NF
        l2_oh = $(NF-1)
    }
    /stalls_l3_miss/ {
        l3_cnt = $NF
        l3_oh = $(NF-1)
        diff_cnt = l2_cnt - l3_cnt
        diff_oh = (diff_cnt / total_l2) * 100
        printf "%s\t%d\t%d\t%d\t%.2f\n", sym, l2_cnt, l3_cnt, diff_cnt, diff_oh
    }
    

    保存为calc_diff.awk后运行:awk -f calc_diff.awk perf_events.txt

方案二:分别导出两份独立perf文件的数据再关联

如果已经有两份独立的perf文件,可以用这种方式:

  1. 分别导出两份文件的符号、计数和占比:

    perf report -n --stdio -F symbol,period,overhead --input perf_l2.data > perf_l2.txt
    perf report -n --stdio -F symbol,period,overhead --input perf_l3.data > perf_l3.txt
    
  2. 用join和awk关联符号并计算差值:

    join -1 1 -2 1 <(sort perf_l2.txt) <(sort perf_l3.txt) | awk '{
        diff_cnt = $2 - $4
        diff_oh = $3 - $5
        printf "%s\t%d\t%d\t%d\t%.2f%%\n", $1, $2, $4, diff_cnt, diff_oh
    }' > l2_only_stalls.txt
    
    • sort确保符号能被join正确匹配,注意提前确保两份文件的符号解析环境一致(比如同一版本的调试符号)

方案三:用perf script导出原始采样数据统计

如果需要更细粒度的调用栈级分析,可以用这种方式:

  1. 录制包含两个事件和调用栈的数据:

    perf record -e cycle_activity.stalls_l2_miss,cycle_activity.stalls_l3_miss -g ./你的程序
    
  2. 导出原始采样数据:

    perf script > perf_script_raw.txt
    
  3. 用Python脚本统计调用栈级别的差值(示例思路):

    from collections import defaultdict
    
    stack_counts = defaultdict(lambda: {'l2': 0, 'l3': 0})
    current_stack = []
    
    with open('perf_script_raw.txt', 'r') as f:
        for line in f:
            line = line.strip()
            if not line:
                # 空行表示采样结束,将当前栈转为字符串作为key
                if current_stack:
                    stack_key = ';'.join(reversed(current_stack))
                    current_stack = []
                continue
            # 判断事件类型
            if 'cycle_activity.stalls_l2_miss' in line:
                event_type = 'l2'
            elif 'cycle_activity.stalls_l3_miss' in line:
                event_type = 'l3'
            else:
                # 提取栈帧符号(适配perf script的输出格式)
                parts = line.split()
                if len(parts) >= 2:
                    current_stack.append(parts[-2])
                continue
            # 统计对应栈的事件数
            if stack_key:
                stack_counts[stack_key][event_type] += 1
    
    # 输出结果
    print("调用栈\tL2停顿\tL3停顿\t仅L2停顿")
    print("----------------------------------------")
    for stack, cnt in stack_counts.items():
        diff = cnt['l2'] - cnt['l3']
        if diff > 0:
            print(f"{stack}\t{cnt['l2']}\t{cnt['l3']}\t{diff}")
    

注意事项

  • 若分开录制两份perf文件,必须保证程序运行的输入、环境完全一致,否则计数差异可能来自程序行为变化,而非事件本身。
  • 调用栈分析时,需要确保程序有完整的调试符号(编译时加-g参数),否则符号会显示为地址。

内容的提问来源于stack exchange,提问作者ajp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 04:06:22