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

x86/Linux多线程:perf报告子项百分比总和与父项不匹配咨询

问题:perf report 中符号百分比求和与父项不匹配的原因

示例代码

#define _GNU_SOURCE

#include <stdatomic.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sched.h>
#include <syscall.h>
#include <linux/futex.h>

volatile atomic_int variable;
int futex_word;

int foo(void *v)
{
    while (1)
    {
        int expected = atomic_load(&variable);
        atomic_compare_exchange_strong(&variable, &expected, expected + 1);
        syscall(SYS_futex, &futex_word, FUTEX_WAKE, 1);
    }
}

int main(void)
{
    void *stack = (char *)mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0) + 4096;
    clone(foo, stack, CLONE_CHILD_SETTID, NULL);
    sleep(1000);
}

运行命令

编译代码生成可执行文件main后,执行采样命令:

sudo perf record --call-graph dwarf,16384 -F 9123 ./main

随后生成性能报告:

sudo perf report

异常现象

得到的报告显示:展开符号foo后包含两个子条目,分别是95.53% foo和0.93% __GI___clone;子项百分比求和为96.46%,但父项foo显示的总占比是96.52%,二者存在微小偏差。

原因分析

这种偏差是正常现象,主要来自两个方面:

  1. 采样的统计误差
    perf采用基于事件的采样机制(此处为9123Hz频率的CPU周期采样),每次采样仅记录当前瞬间的调用栈,属于概率性统计而非精确计数。采样过程中必然存在微小的统计波动,导致最终百分比数值出现偏差。

  2. 四舍五入的累计影响
    报告中显示的百分比均为四舍五入保留两位小数的结果:

  • 子项的百分比是各自独立四舍五入后的数值
  • 父项的百分比是基于该符号的总采样数直接计算后四舍五入的数值
    两者计算逻辑不同,子项求和后自然会与父项数值存在微小差异。比如实际子项占比可能是95.526%和0.927%,四舍五入后变成95.53%和0.93%,求和为96.46%;而父项实际总占比是96.518%,四舍五入后显示为96.52%,二者偏差由此产生。

另外,__GI___clone出现在foo的子项中,是因为新线程通过clone创建后,内核会跳转到指定的foo函数入口,采样可能刚好捕获到clone系统调用返回后、线程完全进入foo前的瞬间,属于调用栈回溯的边界正常情况,占比极低无需在意。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 07:22:36