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

如何使用perf测量文件相关系统调用耗时并获取单文件统计数据?

用Perf按单个文件统计系统调用耗时的解决方案

我平时处理这类慢应用排查时,也更倾向用Perf而不是strace——毕竟低开销太重要了,尤其是不能影响线上服务。针对你需要按单个文件统计read/stat操作耗时的需求,我们可以结合perf trace和自定义脚本实现,比单纯的聚合计时更精准。

第一步:用Perf Trace追踪目标系统调用

首先,我们需要用perf trace捕获和文件相关的系统调用,同时关联文件路径(尤其是read调用的文件描述符对应路径)。

如果是追踪运行中的进程,用PID:

perf trace -T -e read,stat,fstat,fstatat --fd-transfer -p <你的进程PID>

如果是启动应用时直接追踪:

perf trace -T -e read,stat,fstat,fstatat --fd-transfer ./你的慢应用

这里的参数说明:

  • -T:显示每个系统调用的耗时
  • -e:指定要追踪的系统调用(覆盖read和各类stat操作)
  • --fd-transfer:关键选项,会自动关联文件描述符(fd)对应的实际文件路径,解决read调用无法直接看到文件的问题

第二步:按文件聚合统计耗时

perf trace会输出每一次系统调用的详细信息,但我们需要按文件聚合。可以用perf script导出结构化数据,再用awk脚本处理。

  1. 先把追踪数据保存到文件(方便后续分析):
perf trace -T -e read,stat,fstat,fstatat --fd-transfer -p <PID> -o perf_trace.data
  1. 编写一个awk脚本(保存为file_syscall_stats.awk),用来聚合统计:
BEGIN {
    printf "%-40s %-12s %-12s %-12s\n", "文件路径", "总调用次数", "总耗时(ms)", "平均耗时(ms)"
    print "-----------------------------------------------------------------------------------------"
}

# 匹配目标系统调用的行
/^(.*) (read|stat|fstat|fstatat)\(/ {
    syscall = $2
    # 提取文件路径
    if (syscall ~ /stat/) {
        # 处理stat类调用,提取引号中的路径
        if (match($0, /"([^"]+)"/, path_match)) {
            file = path_match[1]
        } else {
            file = "未知路径"
        }
    } else if (syscall == "read") {
        # 处理read调用,提取fd对应的文件路径(靠--fd-transfer的输出)
        if (match($0, /\(([0-9]+)<([^>]+)>/, fd_match)) {
            file = fd_match[2]
        } else {
            file = "未知FD_" $3
        }
    }
    # 提取耗时(转成毫秒)
    if (match($0, /<([0-9.]+)>/, time_match)) {
        elapsed_ms = time_match[1] * 1000
        total_time[file] += elapsed_ms
        call_count[file] += 1
    }
}

END {
    # 按总耗时排序输出(可选)
    PROCINFO["sorted_in"] = "@val_num_desc"
    for (file in total_time) {
        avg_ms = total_time[file] / call_count[file]
        printf "%-40s %-12d %-12.3f %-12.3f\n", file, call_count[file], total_time[file], avg_ms
    }
}
  1. 运行脚本统计:
perf script -i perf_trace.data | awk -f file_syscall_stats.awk

额外技巧

  • 如果想实时看到统计结果,不需要保存文件,直接管道运行:
    perf trace -T -e read,stat,fstat,fstatat --fd-transfer -p <PID> | awk -f file_syscall_stats.awk
    
  • 如果遇到符号链接或者临时文件,--fd-transfer会追踪到实际路径,不用担心统计不准
  • 可以根据需要添加更多系统调用,比如open、pread等,只要在-e参数里加上就行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:30:41