我会一一解释你的猜测。
案例 2
使用perf stat -all-cpus --no-aggr:
./perf stat -vvv -all-cpus --no-aggr ls [957/1827]
Using CPUID GenuineIntel-6-4F
intel_pt default config: tsc,pt,branch
------------------------------------------------------------
perf_event_attr:
type 1
size 112
sample_type IDENTIFIER
read_format TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
disabled 1
inherit 1
exclude_guest 1
------------------------------------------------------------
sys_perf_event_open: pid -1 cpu 0 group_fd -1 flags 0x8 = 3
sys_perf_event_open: pid -1 cpu 1 group_fd -1 flags 0x8 = 4
sys_perf_event_open: pid -1 cpu 2 group_fd -1 flags 0x8 = 5
sys_perf_event_open: pid -1 cpu 3 group_fd -1 flags 0x8 = 7
sys_perf_event_open: pid -1 cpu 4 group_fd -1 flags 0x8 = 8
sys_perf_event_open: pid -1 cpu 5 group_fd -1 flags 0x8 = 9
sys_perf_event_open: pid -1 cpu 6 group_fd -1 flags 0x8 = 10
sys_perf_event_open: pid -1 cpu 7 group_fd -1 flags 0x8 = 11
---------------------------------------------------------------
CPU0 7.628452 cpu-clock (msec) # 0.509 CPUs utilized
CPU1 7.622132 cpu-clock (msec) # 0.509 CPUs utilized
CPU2 7.648510 cpu-clock (msec) # 0.511 CPUs utilized
CPU3 7.644246 cpu-clock (msec) # 0.510 CPUs utilized
CPU4 7.670066 cpu-clock (msec) # 0.512 CPUs utilized
CPU5 7.689670 cpu-clock (msec) # 0.513 CPUs utilized
CPU6 7.687918 cpu-clock (msec) # 0.513 CPUs utilized
CPU7 7.715103 cpu-clock (msec) # 0.515 CPUs utilized
对sys_perf_event_open 的调用反映了pid = -1,这意味着与命令ls 关联的pid 未被测量。这些是per-CPU 测量的特征,这意味着事件cpu-clock 针对特定的CPU 而不是特定的任务。将监视在该特定 CPU 上运行的所有线程。每个 CPU 都将独立开始测量。这些测量只会持续到命令ls 执行。
cpu-clock事件(以及task-clock)事件使用软件hrtimer进行采样。在测量开始时,函数cpu_clock_event_start here 设置具有如下采样周期的hrtimer-
} else {
period = max_t(u64, 10000, hwc->sample_period);
}
hrtimer_start(&hwc->hrtimer, ns_to_ktime(period),
HRTIMER_MODE_REL_PINNED_HARD);
}
hrtimer 过期后,perf_swevent_hrtimer 函数将定期读取并更新cpu-clock 计数器值。 cpu-clock 的值反映了最后一个采样值和当前采样值之间的运行差异(以 jiffies 为单位)。要获得 % CPU 利用率,请将cpu-clock 值除以命令运行所用的挂钟时间。
该命令运行所用的挂钟时间保持在here。特别是看t1和t0的计算。
所以 2) 应该是 --> 在分解的情况下,“它是在命令执行期间运行在该 CPU 上的所有线程使用的 CPU 的一部分。”
案例 1:
使用perf stat <command>
./perf stat -vvv ls
Using CPUID GenuineIntel-6-4F
intel_pt default config: tsc,pt,branch
------------------------------------------------------------
perf_event_attr:
type 1
size 112
config 0x1
sample_type IDENTIFIER
read_format TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
disabled 1
inherit 1
enable_on_exec 1
exclude_guest 1
------------------------------------------------------------
sys_perf_event_open: pid 1833 cpu -1 group_fd -1 flags 0x8 = 3
------------------------------------------------------------
2.120763 task-clock (msec) # 0.038 CPUs utilized
现在对sys_perf_event_open 的调用反映了pid=1833,它是与命令ls 关联的进程的pid。然而,CPU = -1 的值意味着每当这个进程被调度时,不管它被调度到哪个 CPU,计数task-clock 的软件 hrtimer 都会被更新。请注意,此计数现在将特定于进程以及仅与此进程关联的所有线程。
调度程序在perf_event_task_sched_in 和perf_event_task_sched_out 函数的帮助下维护有关进程何时被调度和调度的信息。函数update_context_time 维护任务执行的总时间。
static void update_context_time(struct perf_event_context *ctx)
{
u64 now = perf_clock();
ctx->time += now - ctx->timestamp;
ctx->timestamp = now;
}
ctx->time 维护任务在任何特定 CPU 上执行的总时间。 ctx->timestamp 值维护软件 hrtimer 过期的时间戳,或与此进程关联的事件被调度,或事件被禁用。
该比率的计算现在是进程在任何 CPU 上执行的总时间除以进程执行的挂钟时间。挂钟时间计算与案例 2 相同。