在Linux上搜索可以使用perf_events监视的内容,我找不到内核PMU事件是什么?
也就是说,使用perf版本3.13.11-ckt39,perf列表显示如下事件:
branch-instructions OR cpu/branch-instructions/ [Kernel PMU event]
总的来说有:
Tracepoint event
Software event
Hardware event
Hardware cache event
Raw hardware event descriptor
Hardware breakpoint
Kernel PMU event
我想知道它们是什么,它们来自哪里.我对所有人都有一些解释,但是内核PMU事件项.
从perf wiki tutorial和Brendan Gregg’s page我得到:
>跟踪点是最清晰的 – 这些是内核源上的宏,它们是监视的探测点,它们是用ftrace项目引入的,现在被大家使用
>软件是内核的低级计数器和一些内部数据结构(因此,它们与跟踪点不同)
>硬件事件是一些非常基本的CPU事件,可在所有体系结构中找到,并且可以通过内核轻松访问
>硬件缓存事件是原始硬件事件描述符的昵称 – 它的工作原理如下
因为我得到它,原始硬件事件描述符是比硬件事件更多(微?)架构特定事件,事件来自处理器监控单元(PMU)或给定处理器的其他特定功能,因此它们仅在某些微处理器上可用-architectures(假设“架构”的意思是“x86_64”,其余的实现细节都是“微架构”);
并且可以通过这些奇怪的描述符访问它们
rNNN [Raw hardware event descriptor]
cpu/t1=v1[,t2=v2,t3 ...]/modifier [Raw hardware event descriptor]
(see 'man perf-list' on how to encode it)
– 这些描述符,它们指向的事件等等都可以在处理器手册中找到(PMU events in perf wiki);
但是,当人们知道某个处理器上有一些有用的事件时,他们会给它一个昵称并将其作为硬件缓存事件插入linux,以便于访问
– 如果我错了,请纠正我(奇怪的是,所有硬件缓存事件都是关于某些东西 – 负载或某些东西 – 未命中 – 非常类似于实际处理器的缓存……)
>现在,硬件断点
mem:<addr>[:access] [Hardware breakpoint]
是一个硬件功能,这可能是大多数现代架构常见的,并在调试器中作为断点工作? (无论如何它可能是googlable)
>最后,内核PMU事件我没有设法google;
它也没有出现在the listing of Events in Brendan’s perf
page,所以它是新的?
也许它只是来自PMU的硬件事件的昵称? (为了便于访问,除了昵称之外,它还在事件列表中有一个单独的部分.)
事实上,硬件缓存事件可能是来自CPU缓存的硬件事件的昵称,而内核PMU事件是PMU事件的昵称吗? (为什么不称它为硬件PMU事件呢?..)
它可能只是新的命名方案 – 硬件事件的昵称被分割了?
这些事件指的是像cpu / mem-stores /这样的东西,因为一些linux版本的事件在/ sys / devices /中得到了描述:
# find /sys/ -type d -name events
/sys/devices/cpu/events
/sys/devices/uncore_cbox_0/events
/sys/devices/uncore_cbox_1/events
/sys/kernel/debug/tracing/events
– 调试/跟踪用于ftrace和tracepoints,其他目录与perf列表显示的内核PMU事件完全匹配.
有人能指出我对Kernel PMU事件或/sys/..events/系统是什么的一个很好的解释/文档吗?
另外,/ sys /..events /是一些系统化硬件事件或类似事情的新工作吗? (然后,内核PMU就像“内核的性能监视单元”.)
PS
为了提供更好的上下文,没有特权运行的perf列表(跟踪点没有显示,但是它们中的所有1374都在那里),其中列出了内核PMU事件和硬件缓存事件以及其他事件:
$perf list
List of pre-defined events (to be used in -e):
cpu-cycles OR cycles [Hardware event]
instructions [Hardware event]
...
cpu-clock [Software event]
task-clock [Software event]
...
L1-dcache-load-misses [Hardware cache event]
L1-dcache-store-misses [Hardware cache event]
L1-dcache-prefetch-misses [Hardware cache event]
L1-icache-load-misses [Hardware cache event]
LLC-loads [Hardware cache event]
LLC-stores [Hardware cache event]
LLC-prefetches [Hardware cache event]
dTLB-load-misses [Hardware cache event]
dTLB-store-misses [Hardware cache event]
iTLB-loads [Hardware cache event]
iTLB-load-misses [Hardware cache event]
branch-loads [Hardware cache event]
branch-load-misses [Hardware cache event]
branch-instructions OR cpu/branch-instructions/ [Kernel PMU event]
branch-misses OR cpu/branch-misses/ [Kernel PMU event]
bus-cycles OR cpu/bus-cycles/ [Kernel PMU event]
cache-misses OR cpu/cache-misses/ [Kernel PMU event]
cache-references OR cpu/cache-references/ [Kernel PMU event]
cpu-cycles OR cpu/cpu-cycles/ [Kernel PMU event]
instructions OR cpu/instructions/ [Kernel PMU event]
mem-loads OR cpu/mem-loads/ [Kernel PMU event]
mem-stores OR cpu/mem-stores/ [Kernel PMU event]
ref-cycles OR cpu/ref-cycles/ [Kernel PMU event]
stalled-cycles-frontend OR cpu/stalled-cycles-frontend/ [Kernel PMU event]
uncore_cbox_0/clockticks/ [Kernel PMU event]
uncore_cbox_1/clockticks/ [Kernel PMU event]
rNNN [Raw hardware event descriptor]
cpu/t1=v1[,t2=v2,t3 ...]/modifier [Raw hardware event descriptor]
(see 'man perf-list' on how to encode it)
mem:<addr>[:access] [Hardware breakpoint]
[ Tracepoints not available: Permission denied ]
解决方法:
谷歌搜索和确认结束了!我有一些答案.
但首先让我澄清一下这个问题的目的:
我想清楚地区分系统中的独立进程及其性能计数器.例如,处理器的核心,非核心设备(最近了解它),处理器上的内核或用户应用程序,总线(=总线控制器),硬盘驱动器都是独立的进程,它们不是由时钟同步的.现在可能所有人都有一些过程监控计数器(PMC).我想了解计数器来自哪些进程. (它也有助于谷歌搜索:事物的“供应商”更好地归零.)
另外,用于搜索的设备:Ubuntu 14.04,linux 3.13.0-103-generic,处理器Intel(R)Core(TM)i5-3317U CPU @ 1.70GHz(来自/ proc / cpuinfo,它有2个物理内核和4虚拟 – 这里的物质问题).
术语,问题涉及的事情
来自英特尔:
> processor is a core
device (it’s 1 device/process) and a bunch of uncore
devices,核心是运行程序(时钟,ALU,寄存器等),uncore是放在芯片上的设备,接近处理器的速度和低延迟(真正的原因是“因为制造商可以做到”);据我所知,它基本上是北桥,就像PC主板一样,加上缓存;而AMD实际上将这些设备称为NorthBridge,而不是`
> ubox出现在我的sysfs中
$find /sys/devices/ -type d -name events
/sys/devices/cpu/events
/sys/devices/uncore_cbox_0/events
/sys/devices/uncore_cbox_1/events
– 是一个非核心设备,它管理最后一级缓存(LLC,在击中RAM之前的最后一个缓存);我有2个核心,因此2个LLC和2个ubox;
>处理器监控单元(PMU)是一个独立的设备,它监控处理器的操作并将它们记录在处理器监控计数器(PMC)中(计算缓存未命中,处理器周期等);它们存在于核心和非核心设备上;使用rdpmc(读取PMC)指令访问核心数据; uncore,因为这些设备依赖于手边的实际处理器,通过rdmsr(自然)通过模型特定寄存器(MSR)访问;
显然,它们的工作流程是通过成对的寄存器完成的 – 1个寄存器组,计数器计数的事件,2个寄存器是计数器中的值;计数器可以配置为在一堆事件之后递增,而不仅仅是1;在这些柜台中有一些中断/技术注意到溢出;
>更多人可以在英特尔的“IA-32软件开发人员手册第3B卷”第18章“性能监控”中找到;
此外,MSR的格式具体针对这些非核心PMC版本“架构性能监控版本1”(手册中有版本1-4,我不知道哪一个是我的处理器)在“图18-1”中描述. IA32_PERFEVTSELx MSR的布局“(我的第18-3页)和”18.2.1.2预定义的架构性能事件“部分”表18-1.用于预定义的架构性能事件的UMask和事件选择编码“,其中显示在perf列表中显示为Hardware事件的事件.
来自linux内核:
> kernel有一个系统(抽象/层),用于管理不同来源的性能计数器,包括软件(内核)和硬件,它在linux-source-3.13.0 / tools / perf / design.txt中描述;这个系统中的一个事件被定义为struct perf_event_attr(文件linux-source-3.13.0 / include / uapi / linux / perf_event.h),其主要部分可能是__u64配置字段 – 它可以同时拥有一个CPU-特定事件定义(英特尔图中描述的格式为64位字)或内核事件
The MSB of the config word signifies if the rest contains [raw CPU’s or kernel’s event]
内核的事件定义为7位用于类型,56用于事件的标识符,它们是代码中的枚举,在我的例子中是:
$ak PERF_TYPE linux-source-3.13.0/include/
...
linux-source-3.13.0/include/uapi/linux/perf_event.h
29: PERF_TYPE_HARDWARE = 0,
30: PERF_TYPE_SOFTWARE = 1,
31: PERF_TYPE_TRACEPOINT = 2,
32: PERF_TYPE_HW_CACHE = 3,
33: PERF_TYPE_RAW = 4,
34: PERF_TYPE_BREAKPOINT = 5,
36: PERF_TYPE_MAX, /* non-ABI */
(ak是我对ack-grep的别名,这是Debian上ack的名字;而ack很棒);
在内核的源代码中,可以看到诸如“注册在系统上发现的所有PMU”和结构类型struct pmu之类的操作,这些操作被传递给类似int perf_pmu_register(struct pmu * pmu,const char * name,int type) – 因此,人们可以称这个系统为“内核的PMU”,这将是系统中所有PMU的聚合;但是这个名字可能被解释为内核操作的监控系统,这会产生误导;
为了清楚起见,我们称这个子系统为perf_events;
>作为任何内核子系统,该子系统可以导出到sysfs(用于导出内核子系统供人们使用);那是我的/ sys /中的那些事件目录 – 导出的(部分?)perf_events子系统;
>此外,用户空间实用程序perf(内置于linux)仍然是一个单独的程序,并具有自己的抽象;它代表一个事件请求用户监视为perf_evsel(文件linux-source-3.13.0 / tools / perf / util / evsel.{h,c}) – 这个结构有一个字段struct perf_event_attr attr;,但也是一个像struct cpu_map * cpus这样的字段;这就是perf实用程序如何为所有或特定CPU分配事件.
回答
>实际上,硬件缓存事件是高速缓存设备(英特尔非核设备的ubox)事件的“快捷方式”,这些事件是特定于处理器的,并且可以通过协议Raw硬件事件描述符进行访问.并且硬件事件在架构中更稳定,据我所知,它从核心设备命名事件.我的内核3.13中没有其他“快捷方式”可用于其他一些非核心事件和计数器.所有其余的 – 软件和跟踪点 – 是内核的事件.
我想知道核心的硬件事件是否通过相同的原始硬件事件描述符协议访问.他们可能没有 – 因为计数器/ PMU位于核心,也许它的访问方式不同.例如,使用rdpmu指令代替rdmsr,它访问非核心.但它并不重要.
>内核PMU事件只是事件,它们被导出到sysfs中.我不知道这是怎么做的(内核自动在系统上发现所有PMC,或者只是硬编码的东西,如果我添加一个kprobe – 它是否被导出?等等).但重点是这些事件与硬件事件或内部perf_event系统中的任何其他事件相同.
我不知道那些是什么
$ls /sys/devices/uncore_cbox_0/events
clockticks
是.
有关内核PMU事件的详细信息
搜索代码会导致:
$ak "Kernel PMU" linux-source-3.13.0/tools/perf/
linux-source-3.13.0/tools/perf/util/pmu.c
629: printf(" %-50s [Kernel PMU event]\n", aliases[j]);
– 在函数中发生
void print_pmu_events(const char *event_glob, bool name_only) {
...
while ((pmu = perf_pmu__scan(pmu)) != NULL)
list_for_each_entry(alias, &pmu->aliases, list) {...}
...
/* b.t.w. list_for_each_entry is an iterator
* apparently, it takes a block of {code} and runs over some lost
* Ruby built in kernel!
*/
// then there is a loop over these aliases and
loop{ ... printf(" %-50s [Kernel PMU event]\n", aliases[j]); ... }
}
和perf_pmu__scan在同一个文件中:
struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) {
...
pmu_read_sysfs(); // that's what it calls
}
– 也在同一个文件中:
/* Add all pmus in sysfs to pmu list: */
static void pmu_read_sysfs(void) {...}
而已.
硬件事件和硬件缓存事件的详细信息
显然,硬件事件来自英特尔称之为“预定义的架构性能事件”,IA-32软件开发人员手册第3B卷中的18.2.1.2.本手册的“18.1性能监控概述”将其描述为:
The second class of performance monitoring capabilities is referred to as architectural performance monitoring.
This class supports the same counting and Interrupt-based event sampling usages, with a smaller set of available
events.
The visible behavior of architectural performance events is consistent across processor implementations.
Availability of architectural performance monitoring capabilities is enumerated using the CPUID.0AH. These events are discussed in Section 18.2.
– 另一种是:
Starting with Intel Core Solo and Intel Core Duo processors, there are two classes of performance monitoring capa-bilities.
The first class supports events for monitoring performance using counting or interrupt-based event sampling usage.
These events are non-architectural and vary from one processor model to another…
这些事件确实只是潜在的“原始”硬件事件的链接,可以通过perf实用程序作为Raw硬件事件描述符进行访问.
要查看这个,请查看linux-source-3.13.0 / arch / x86 / kernel / cpu / perf_event_intel.c:
/*
* Intel PerfMon, used on Core and later.
*/
static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly =
{
[PERF_COUNT_HW_CPU_CYCLES] = 0x003c,
[PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0,
[PERF_COUNT_HW_CACHE_REFERENCES] = 0x4f2e,
[PERF_COUNT_HW_CACHE_MISSES] = 0x412e,
...
}
– 对于“LLC未命中”,“表18-1.预定义建筑性能事件的UMask和事件选择编码”中找到了正确的0x412e:
Bit Position CPUID.AH.EBX | Event Name | UMask | Event Select
...
4 | LLC Misses | 41H | 2EH
– H代表十六进制.所有7都在结构中,加上[PERF_COUNT_HW_REF_CPU_CYCLES] = 0x0300,/ *伪编码*. (命名有点不同,地址相同.)
然后硬件缓存事件处于(在同一文件中)的结构中:
static __initconst const u64 snb_hw_cache_extra_regs
[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] =
{...}
– 应该是沙桥?
其中一个 – snb_hw_cache_extra_regs [LL] [OP_WRITE] [RESULT_ACCESS]填充了SNB_DMND_WRITE | SNB_L3_ACCESS,其中来自上面的def-s:
#define SNB_L3_ACCESS SNB_RESP_ANY
#define SNB_RESP_ANY (1ULL << 16)
#define SNB_DMND_WRITE (SNB_DMND_RFO|SNB_LLC_RFO)
#define SNB_DMND_RFO (1ULL << 1)
#define SNB_LLC_RFO (1ULL << 8)
它应该等于0x00010102,但我不知道如何用一些表检查它.
这给出了如何在perf_events中使用它的想法:
$ak hw_cache_extra_regs linux-source-3.13.0/arch/x86/kernel/cpu/
linux-source-3.13.0/arch/x86/kernel/cpu/perf_event.c
50:u64 __read_mostly hw_cache_extra_regs
292: attr->config1 = hw_cache_extra_regs[cache_type][cache_op][cache_result];
linux-source-3.13.0/arch/x86/kernel/cpu/perf_event.h
521:extern u64 __read_mostly hw_cache_extra_regs
linux-source-3.13.0/arch/x86/kernel/cpu/perf_event_intel.c
272:static __initconst const u64 snb_hw_cache_extra_regs
567:static __initconst const u64 nehalem_hw_cache_extra_regs
915:static __initconst const u64 slm_hw_cache_extra_regs
2364: memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
2365: sizeof(hw_cache_extra_regs));
2407: memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs,
2408: sizeof(hw_cache_extra_regs));
2424: memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
2425: sizeof(hw_cache_extra_regs));
2452: memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
2453: sizeof(hw_cache_extra_regs));
2483: memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
2484: sizeof(hw_cache_extra_regs));
2516: memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
$
memcpys在__init int intel_pmu_init(void){… case:…}中完成.
只有attr-> config1有点奇怪.但它存在于perf_event_attr(相同的linux-source-3.13.0 / include / uapi / linux / perf_event.h文件)中:
...
union {
__u64 bp_addr;
__u64 config1; /* extension of config */
};
union {
__u64 bp_len;
__u64 config2; /* extension of config1 */
};
...
它们在kernel的perf_events系统中注册,调用int perf_pmu_register(struct pmu * pmu,const char * name,int type)(在linux-source-3.13.0 / kernel / events / core.c中定义:):
> static int __init init_hw_perf_events(void)(file arch / x86 / kernel / cpu / perf_event.c),调用perf_pmu_register(& pmu,“cpu”,PERF_TYPE_RAW);
> static int __init uncore_pmu_register(struct intel_uncore_pmu * pmu)(文件arch / x86 / kernel / cpu / perf_event_intel_uncore.c,还有arch / x86 / kernel / cpu / perf_event_amd_uncore.c),调用ret = perf_pmu_register(& pmu- > pmu,pmu-> name,-1);
最后,所有事件都来自硬件,一切都很好.但是在这里我们可以注意到:为什么我们在perf列表中有LLC负载而不是ubox1 LLC负载,因为这些是HW事件,它们实际上来自ubox?
这是perf实用程序及其’perf_evsel结构:当你从perf请求HW事件时,你定义了你想要它的处理器的事件(默认是全部),并且它设置了具有所请求的事件和处理器的perf_evsel,然后在聚合时将perf_evsel中所有处理器的计数器相加(或者用它们做一些其他统计).
可以在tools / perf / builtin-stat.c中看到它:
/*
* Read out the results of a single counter:
* aggregate counts across CPUs in system-wide mode
*/
static int read_counter_aggr(struct perf_evsel *counter)
{
struct perf_stat *ps = counter->priv;
u64 *count = counter->counts->aggr.values;
int i;
if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter),
thread_map__nr(evsel_list->threads), scale) < 0)
return -1;
for (i = 0; i < 3; i++)
update_stats(&ps->res_stats[i], count[i]);
if (verbose) {
fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
perf_evsel__name(counter), count[0], count[1], count[2]);
}
/*
* Save the full runtime - to allow normalization during printout:
*/
update_shadow_stats(counter, count);
return 0;
}
(因此,对于实用程序perf,“单个计数器”甚至不是perf_event_attr,这是适合SW和HW事件的一般形式,它是您查询的事件 – 相同的事件可能来自不同的设备,它们汇总.)
另外一个注意事项:struct perf_evsel只包含1个struct perf_evevent_attr,但它也有一个字段struct perf_evsel * leader; – 它是嵌套的.
perf_events中有一个“(分层的)事件组”的功能,当你可以将一堆计数器一起分派时,它们可以相互比较,依此类推.不知道它如何与来自内核,核心,ubox的独立事件一起工作.但是这个perf_evsel的嵌套就是它.并且,很可能,这就是perf如何一起管理多个事件的查询.