正在寻找什么可以perf_events
在Linux上监控,我找不到什么Kernel PMU event
?也就是说,随着perf version 3.13.11-ckt39
节目perf list
事件,如:
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
我想了解它们是什么,它们来自哪里。我对所有人都有某种解释,但Kernel PMU event
项目除外。
从perf wiki 教程和布伦丹·格雷格的页面我明白了:
Tracepoints
最清晰的——这些是内核源代码中的宏,它们为监控提供了一个探针点,它们是随ftrace
项目引入的,现在被每个人使用Software
是内核的低级计数器和一些内部数据结构(因此,它们与跟踪点不同)Hardware event
是一些非常基本的 CPU 事件,可以在全部架构并以某种方式很容易被内核访问Hardware cache event
是昵称Raw hardware event descriptor
——它的工作原理如下据我了解,
Raw hardware event descriptor
更多(微?)体系结构特定的事件比Hardware event
,这些事件来自处理器监控单元(PMU)或给定处理器的其他特定功能,因此它们仅在某些微体系结构上可用(比方说“架构”意味着“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)
-- 这些描述符,它们指向哪些事件等等可以在处理器手册中找到(perf wiki 中的 PMU 事件);
但是,当人们知道给定处理器上有一些有用的事件时,他们会给它一个昵称并将其插入 Linux 以便
Hardware cache event
于访问-- 如果我错了,请纠正我(奇怪的是,所有这些
Hardware cache event
都是关于something-loads
或something-misses
-- 非常像实际处理器的缓存..)现在
Hardware breakpoint
mem:<addr>[:access] [Hardware breakpoint]
是一种硬件功能,这可能是大多数现代体系结构所共有的,并且可以用作调试器中的断点? (无论如何可能它是谷歌搜索的)
最后,
Kernel PMU event
我没能用谷歌搜索;它也没有出现在Brendan 性能页面中的事件列表,所以这是新的?
也许这只是专门来自 PMU 的硬件事件的昵称? (为了便于访问,除了昵称之外,事件列表中还有一个单独的部分。)事实上,
Hardware cache events
昵称可能是来自 CPU 缓存的硬件事件,也是Kernel PMU event
PMU 事件的昵称吗? (为什么不Hardware PMU event
这么称呼它?..)这可能只是新的命名方案——硬件事件的昵称被分段了?这些事件指的是
cpu/mem-stores/
, plus 之类的东西,因为一些 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
--
debug/tracing
用于ftrace
和跟踪点,其他目录perf list
与显示的内容完全匹配Kernel PMU event
。
有人能给我提供关于系统是什么的很好的解释/文档Kernel PMU events
吗/sys/..events/
?另外,是否有/sys/..events/
一些新的努力将硬件事件系统化或类似的事情? (那么,Kernel PMU就相当于“内核的性能监控单元”。)
聚苯乙烯
为了提供更好的上下文,非特权运行perf list
(未显示跟踪点,但所有 1374 个跟踪点都在那里),并跳过了Kernel PMU event
s 和s 的完整列表:Hardware cache event
$ 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 ]
答案1
谷歌搜索和ack
-ing结束了!我有一些答案。
但首先让我再澄清一下问题的目的:我想清楚地区分系统中的独立进程及其性能计数器。例如,处理器的核心、非核心设备(最近了解到)、处理器上的内核或用户应用程序、总线(=总线控制器)、硬盘驱动器都是独立的进程,它们不被时钟同步。如今,它们可能都有一些进程监控计数器(PMC)。我想了解计数器来自哪些进程。 (这对于谷歌搜索也很有帮助:事物的“供应商”可以更好地将其归零。)
另外,用于搜索的装备:Ubuntu 14.04
、linux 3.13.0-103-generic
、 处理器Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz
(来自/proc/cpuinfo
,它有 2 个物理核心和 4 个虚拟核心 - 这里的物理问题)。
术语、问题涉及的内容
来自英特尔:
处理器是一个
core
设备(它是 1 个设备/进程)和一堆uncore
设备,core
是运行程序的(时钟、ALU、寄存器等),uncore
是放置在芯片上的设备,靠近处理器以实现速度和低延迟(真正的原因是“因为制造商可以做到”);据我了解,它基本上是北桥,就像 PC 主板上的一样,加上缓存; AMD 实际上称这些设备北桥为instead of
“非核心”;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
-- 是一个
uncore
设备,管理最后一级缓存(LLC,命中 RAM 之前的最后一级缓存);我有 2 个核心,因此 2 个 LLC 和 2 个ubox
;处理器监控单元 (PMU) 是一个独立的设备,用于监控处理器的操作并将其记录在处理器监控计数器 (PMC) 中(对缓存未命中、处理器周期等进行计数);它们存在于
core
和uncore
设备上;这些core
是通过rdpmc
(读PMC)指令访问的;由于uncore
这些设备依赖于手头的实际处理器,因此可以通过(自然地)通过模型特定寄存器(MSR)访问rdmsr
;显然,它们的工作流程是通过寄存器对完成的——1个寄存器设置计数器计数哪些事件,2个寄存器是计数器中的值;计数器可以配置为在一堆事件发生后递增,而不仅仅是 1; + 有一些中断/技术注意到这些计数器溢出;
更多内容可以在 Intel 的《IA-32 Software Developer's Manual Vol 3B》第 18 章“性能监控”中找到;
另外,“架构性能监控版本1”版本的这些PMC的MSR具体格式
uncore
(手册中有版本1-4,我不知道哪一个是我的处理器)在“图18-1.布局”中描述IA32_PERFEVTSELx MSR”(我的第 18-3 页),以及“18.2.1.2 预定义架构性能事件”部分和“表 18-1 的预定义架构性能事件的 UMask 和事件选择编码”,其中显示了Hardware event
中显示的事件perf list
。
来自Linux内核:
内核有一个系统(抽象/层),用于管理不同来源的性能计数器,包括软件(内核)和硬件,它在 中进行了描述
linux-source-3.13.0/tools/perf/design.txt
;该系统中的事件被定义为struct perf_event_attr
(filelinux-source-3.13.0/include/uapi/linux/perf_event.h
),其主要部分可能是__u64 config
字段——它可以保存特定于 CPU 的事件定义(Intel 图中描述的格式的 64 位字)或内核的事件配置字的 MSB 表示其余部分是否包含[原始 CPU 或内核事件]
内核事件定义为 7 位类型和 56 位事件标识符,
enum
在代码中是 -s,在我的例子中是:$ 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
是我的别名,它是Debian 上的ack-grep
名称;非常棒);ack
ack
在内核的源代码中,我们可以看到诸如“注册系统上发现的所有 PMU”和结构类型之类的操作
struct pmu
,这些操作被传递给类似的东西int perf_pmu_register(struct pmu *pmu, const char *name, int type)
- 因此,我们可以将此系统称为“内核的 PMU”,这将是一个聚合系统上所有 PMU 的数量;但这个名称可能被解释为内核操作的监视系统,这会产生误导;perf_events
为了清楚起见,我们将此子系统称为;与任何内核子系统一样,这个子系统可以导出到
sysfs
(这是为了导出内核子系统以供人们使用);这就是events
我的/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 的字段。
回答
事实上,它们是高速缓存设备(英特尔设备)
Hardware cache event
事件的“快捷方式” ,它们是特定于处理器的,并且可以通过协议进行访问。并且在架构内更加稳定,据我所知,它命名了设备中的事件。我的内核中没有其他一些事件和计数器的“快捷方式”。所有其余的 -和- 都是内核的事件。ubox
uncore
Raw hardware event descriptor
Hardware event
core
3.13
uncore
Software
Tracepoints
我想知道 是否是
core
通过Hardware event
相同的协议访问的Raw hardware event descriptor
。他们可能不会——因为计数器/PMU 位于 上core
,也许它的访问方式不同。例如,使用该rdpmu
指令,而不是rdmsr
访问uncore
.但这并不那么重要。Kernel PMU event
只是事件,导出到sysfs
.我不知道这是如何完成的(由内核自动在系统上发现所有 PMC,或者只是硬编码的东西,如果我添加kprobe
-- 它会导出吗?等等)。但要点是,这些事件与Hardware event
内部系统中的任何其他事件相同perf_event
。我不知道那些是什么
$ ls /sys/devices/uncore_cbox_0/events clockticks
是。
详细信息Kernel PMU event
搜索代码会导致:
$ 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) {...}
就是这样。
详细信息Hardware event
和Hardware cache event
显然,这Hardware event
来自英特尔所谓的“预定义架构性能事件”,IA-32 软件开发人员手册第 3B 卷中的 18.2.1.2。手册的“18.1性能监控概述”将它们描述为:
第二类性能监控功能称为架构性能监控。此类支持相同的计数和基于中断的事件采样用法,以及较小的可用事件集。架构性能事件的可见行为在处理器实现之间是一致的。使用 CPUID.0AH 枚举架构性能监控功能的可用性。这些事件在 18.2 节中讨论。
-- 另一种类型是:
从英特尔酷睿单核和英特尔酷睿双核处理器开始,有两类性能监控功能。第一类支持使用计数或基于中断的事件采样来监视性能的事件。这些事件是非体系结构的,并且因处理器型号而异......
这些事件实际上只是到底层“原始”硬件事件的链接,可以通过perf
实用程序 as访问这些事件Raw hardware event descriptor
。
要检查这一点,请查看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,
...
}
——确切地说,0x412e
可以在“表 18-1.预定义架构性能事件的 UMask 和事件选择编码”中找到“LLC 未命中”:
Bit Position CPUID.AH.EBX | Event Name | UMask | Event Select
...
4 | LLC Misses | 41H | 2EH
--H
表示十六进制。所有 7 个都在结构中,加上[PERF_COUNT_HW_REF_CPU_CYCLES] = 0x0300, /* pseudo-encoding *
. (命名有点不同,地址是一样的。)
那么Hardware cache event
s 的结构如下(在同一文件中):
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));
$
smemcpy
是在 中完成的__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 */
};
...
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)
(文件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);
最后,所有事件都来自硬件,一切正常。但这里人们可能会注意到:为什么我们有LLC-loads
inperf list
和 not ubox1 LLC-loads
,因为这些是硬件事件并且它们实际上来自ubox
es ?
perf
这是实用程序及其结构的事情perf_evsel
:当您请求硬件事件时,您定义您希望从哪个处理器获得该事件(默认为全部),并且它使用请求的事件和处理器perf
进行设置,然后在聚合时是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
,它是一种通用形式,适合软件和硬件事件,它是您查询的事件 - 相同的事件可能来自不同的设备,并且它们被聚合.)
另请注意:struct perf_evsel
仅包含 1 struct perf_evevent_attr
,但它还有一个字段struct perf_evsel *leader;
——它是嵌套的。中有一个“(分层)事件组”的功能perf_events
,当您可以将一堆计数器分派在一起时,以便它们可以相互比较等等。不确定它如何处理来自kernel
, core
,的独立事件ubox
。但这个嵌套就是perf_evsel
这样了。而且,最有可能的是,这就是如何perf
管理多个事件的查询。