perf_events 列表中的内核 PMU 事件是什么?

xea*_*its 15 linux performance cpu monitoring perf-event

在搜索什么人能够监测perf_events在Linux上,我找不到什么Kernel PMU event是?也就是说,与perf version 3.13.11-ckt39perf list节目的事件,如:

branch-instructions OR cpu/branch-instructions/    [Kernel PMU event]
Run Code Online (Sandbox Code Playgroud)

总的来说有:

Tracepoint event
Software event
Hardware event
Hardware cache event
Raw hardware event descriptor
Hardware breakpoint
Kernel PMU event
Run Code Online (Sandbox Code Playgroud)

我想了解它们是什么,它们来自哪里。我对所有人都有某种解释,但Kernel PMU event项目。

perf wiki 教程Brendan Gregg 的页面我得到:

  • 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)
    
    Run Code Online (Sandbox Code Playgroud)

    -- 这些描述符,它们指向哪些事件等等可以在处理器手册中找到(perf wiki 中的 PMU 事件);

    但是,当人们知道在给定的处理器上有一些有用的事件时,他们会给它一个昵称并将其插入 linuxHardware cache event以便于访问

    - 如果我错了,请纠正我(奇怪的是所有Hardware cache event关于something-loadssomething-misses- 非常像实际处理器的缓存..)

  • 现在 Hardware breakpoint

    mem:<addr>[:access]                                [Hardware breakpoint]
    
    Run Code Online (Sandbox Code Playgroud)

    是一个硬件特性,它可能是大多数现代架构的共同点,并且在调试器中用作断点?(无论如何它可能是谷歌搜索的)

  • 最后,Kernel PMU event我没能用谷歌搜索;

    它也没有出现在 Brendan's perf page 的 Events 列表中,所以它是新的?

    也许这只是来自 PMU 的硬件事件的昵称?(为了便于访问,除了昵称外,它在事件列表中还有一个单独的部分。)事实上,也许Hardware cache events是 CPU 缓存中硬件事件的Kernel PMU event昵称,而 PMU 事件的昵称?(那为什么不叫它呢Hardware PMU event?..)它可能只是新的命名方案——硬件事件的昵称被分割了?

    这些事件指的是诸如cpu/mem-stores/, 加上因为一些 linux 版本事件在/sys/devices/and 中得到了描述:

    # 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
    
    Run Code Online (Sandbox Code Playgroud)

    --debug/tracing用于ftrace跟踪点,其他目录与perf list显示的内容完全匹配Kernel PMU event

有人可以向我指出什么Kernel PMU events/sys/..events/系统是什么的很好的解释/文档吗?此外,是否/sys/..events/有一些新的努力来系统化硬件事件或类似的东西?(那么,内核 PMU 就像“内核的性能监控单元”。)

聚苯乙烯

为了提供更好的上下文,非特权运行perf list(未显示跟踪点,但所有 1374 个都在那里),并跳过了Kernel PMU events 和Hardware cache events 的完整列表:

$ 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 ]
Run Code Online (Sandbox Code Playgroud)

xea*_*its 15

谷歌搜索和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设备(它是一个设备/进程)和一堆uncore设备core是运行程序(时钟,ALU,寄存器等)uncore的设备,是设备放在芯片上,靠近处理器以提高速度和低延迟(真正的原因)是“因为制造商可以做到”);据我所知,它基本上是北桥,就像在 PC 主板上一样,加上缓存;而 AMD 实际上将这些设备instead of称为 NorthBridge uncore`;

  • 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
    
    Run Code Online (Sandbox Code Playgroud)

    -- 是一个uncore管理Last Level Cache(LLC,命中RAM之前的最后一个)的设备;我有 2 个内核,因此有 2 个 LLC 和 2 个ubox

  • 处理器监控单元 (PMU) 是一个独立的设备,它监控处理器的操作并将它们记录在处理器监控计数器 (PMC) 中(计算缓存未命中、处理器周期等);它们存在于coreuncore设备上;的core那些与访问rdpmc(读PMC)指令; 的uncore,因为这些装置在手取决于实际的处理器,经由经由模型特定的寄存器(MSR)访问rdmsr(自然);

    显然,它们的工作流程是通过成对的寄存器完成的——1 个寄存器设置计数器计数的事件,2 个寄存器是计数器中的值;计数器可以配置为在一系列事件后递增,而不仅仅是 1;+ 在这些计数器中有一些中断/技术注意到溢出;

  • 更多信息可以在英特尔的“IA-32 软件开发人员手册第 3B 卷”第 18 章“性能监控”中找到;

    另外,uncore“Architectural Performance Monitoring Version 1”版本(手册中有版本1-4,我不知道哪个是我的处理器)的这些PMC的MSR格式具体在“图18-1.布局”中描述IA32_PERFEVTSELx MSR”(我的第 18-3 页),以及“18.2.1.2 预定义架构性能事件”和“表 18-1. 预定义架构性能事件的 UMask 和事件选择编码”部分,其中显示了事件,显示为Hardware eventperf list

从 linux 内核:

  • 内核有一个系统(抽象/层)用于管理不同来源的性能计数器,包括软件(内核)和硬件,它在linux-source-3.13.0/tools/perf/design.txt; 该系统中的事件被定义为struct perf_event_attr(file linux-source-3.13.0/include/uapi/linux/perf_event.h),其主要部分可能是__u64 config字段——它可以包含特定于 CPU 的事件定义(英特尔数字中描述的格式的 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 */
    
    Run Code Online (Sandbox Code Playgroud)

    ak是我对 的别名ack-grep,这是ackDebian 上的名称;而且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。

回答

  1. 实际上,Hardware cache event是缓存设备(ubox英特尔uncore设备的)事件的“快捷方式” ,它们是特定于处理器的,可以通过协议访问Raw hardware event descriptor。并且Hardware event在架构中更加稳定,据我所知,它从core设备命名事件。我的内核中没有其他3.13一些uncore事件和计数器的“快捷方式” 。所有其余的——Software以及Tracepoints——都是内核的事件。

    我想知道core'sHardware event是否是通过相同的Raw hardware event descriptor协议访问的。他们可能不会——因为计数器/PMU 位于 上core,也许它的访问方式不同。例如,使用该rdpmu指令,而不是rdmsr,访问uncore。但这并不重要。

  2. Kernel PMU event只是事件,它们被导出到sysfs. 我不知道这是如何完成的(由内核自动在系统上发现所有 PMC,或者只是硬编码的东西,如果我添加kprobe- 它是导出的吗?等)。但重点是这些事件Hardware event与内部perf_event系统中的任何其他事件相同。

    我不知道那些是什么

    $ ls /sys/devices/uncore_cbox_0/events
    clockticks
    
    Run Code Online (Sandbox Code Playgroud)

    是。

详情 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]);
Run Code Online (Sandbox Code Playgroud)

-- 发生在函数中

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]); ... }
}
Run Code Online (Sandbox Code Playgroud)

并且perf_pmu__scan在同一个文件中:

struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) {
    ...
                pmu_read_sysfs(); // that's what it calls
}
Run Code Online (Sandbox Code Playgroud)

-- 也在同一个文件中:

/* Add all pmus in sysfs to pmu list: */
static void pmu_read_sysfs(void) {...}
Run Code Online (Sandbox Code Playgroud)

就是这样。

详情Hardware eventHardware cache event

显然,Hardware event来自英特尔所谓的“预定义架构性能事件”,IA-32 软件开发人员手册第 3B 卷中的 18.2.1.2。手册的“18.1 性能监控概述”将它们描述为:

第二类性能监控功能称为架构性能监控。此类支持相同的计数和基于中断的事件采样用法,但可用事件集较小。架构性能事件的可见行为跨处理器实现是一致的。使用 CPUID.0AH 枚举架构性能监控功能的可用性。这些事件在第 18.2 节中讨论。

-- 另一种是:

从 Intel Core Solo 和 Intel Core Duo 处理器开始,有两类性能监控功能。第一类支持使用计数或基于中断的事件采样使用来监视性能的事件。这些事件是非架构的,从一种处理器模型到另一种处理器模型都不同......

这些事件确实只是指向底层“原始”硬件事件的链接,可以通过perf实用程序作为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,
    ...
}
Run Code Online (Sandbox Code Playgroud)

--0x412e在“表 18-1. 预定义架构性能事件的 UMask 和事件选择编码”中可以找到“LLC 未命中”:

Bit Position CPUID.AH.EBX | Event Name | UMask | Event Select
...
                        4 | LLC Misses | 41H   | 2EH
Run Code Online (Sandbox Code Playgroud)

--H用于十六进制。所有 7 都在结构中,加上[PERF_COUNT_HW_REF_CPU_CYCLES] = 0x0300, /* pseudo-encoding *. (命名有点不同,地址是一样的。)

然后Hardware cache events 的结构类似于(在同一个文件中):

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] =
{...}
Run Code Online (Sandbox Code Playgroud)

-- 沙桥应该是哪个?

其中一个 --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)
Run Code Online (Sandbox Code Playgroud)

这应该等于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));
$
Run Code Online (Sandbox Code Playgroud)

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 */
    };
...
Run Code Online (Sandbox Code Playgroud)

它们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)(file arch/x86/kernel/cpu/perf_event_intel_uncore.c, 还有arch/x86/kernel/cpu/perf_event_amd_uncore.c) with callret = perf_pmu_register(&pmu->pmu, pmu->name, -1);

所以最后,所有事件都来自硬件,一切正常。但是在这里人们可能会注意到:为什么我们有LLC-loadsinperf list而没有ubox1 LLC-loads,因为这些是硬件事件并且它们实际上来自uboxes?

这是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;
}
Run Code Online (Sandbox Code Playgroud)

(因此,对于该实用程序perf,“单个计数器”甚至不是 a perf_event_attr,这是一种通用形式,适合 SW 和 HW 事件,它是您查询的事件——相同的事件可能来自不同的设备,并且它们被聚合.)

还有一个注意事项:struct perf_evsel只包含 1 struct perf_evevent_attr,但它也有一个字段struct perf_evsel *leader;——它是嵌套的。中有一个“(分层)事件组”的特性perf_events,当你可以将一堆计数器分派到一起,以便它们可以相互比较等等。不确定它如何处理来自kernel, core, 的独立事件ubox。但这个嵌套perf_evsel就是这样。而且,最有可能的是,这就是perf一起管理多个事件的查询的方式。