Linux

perf_events 列表中的核心 PMU 事件是什麼?

  • December 5, 2016

在 Linux 上搜尋可以監控的內容,但找不到是什麼?即,顯示事件如下:perf_events``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 tutorialBrendan 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)

– 這些描述符,它們指向的事件等等都可以在處理器手冊中找到(perf wiki 中的 PMU 事件);

但是,當人們知道給定處理器上有一些有用的事件時,他們會給它一個暱稱並將其插入 linuxHardware cache event以便於訪問

– 如果我錯了,請糾正我(奇怪的是,所有這些Hardware cache event都是關於something-loadssomething-misses– 非常像實際處理器的記憶體..)

  • 現在Hardware breakpoint
mem:<addr>[:access]                                [Hardware breakpoint]

是一種硬體功能,可能是大多數現代架構所共有的,並且在調試器中用作斷點?(無論如何它可能是可Google搜尋的)

  • 最後,Kernel PMU event我沒能上Google;

它也沒有出現在 Brendan 的性能頁面中的事件列表中,所以它是新的嗎?

也許它只是專門來自 PMU 的硬體事件的暱稱?(為了便於訪問,它在事件列表中除了暱稱之外還有一個單獨的部分。)事實上,可能Hardware cache events是來自 CPU 記憶體的硬體事件的Kernel PMU event暱稱和 PMU 事件的暱稱?(為什麼不叫它呢Hardware PMU event?..)它可能只是新的命名方案——硬體事件的暱稱被分段了?

這些事件指的是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

debug/tracing用於ftrace和跟踪點,其他目錄完全匹配perf list顯示為Kernel PMU event.

有人可以指出我是什麼Kernel PMU events/sys/..events/系統的一個很好的解釋/文件嗎?此外,是否/sys/..events/有一些新的努力來系統化硬體事件或類似的東西?(那麼,Kernel PMU 就像“Kernel 的性能監控單元”。)

附言

為了提供更好的上下文,沒有特權的執行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 ]

Google搜尋ack結束!我有一些答案。

但首先讓我再澄清一下問題的目的:我想清楚地區分系統中的獨立程序及其性能計數器。例如,處理器的核心,非核心設備(最近了解),處理器上的核心或使用者應用程序,匯流排(=匯流排控制器),硬碟驅動器都是獨立的程序,它們不通過時鐘同步. 現在可能他們都有一些程序監控計數器(PMC)。我想了解計數器來自哪些程序。(它也有助於Google搜尋:事物的“供應商”將其歸零更好。)

此外,用於搜尋的設備:Ubuntu 14.04linux 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 非核心;
  • 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) 中(計數記憶體未命中、處理器週期等);它們存在於coreuncore設備上;那些core通過rdpmc(讀取 PMC)指令訪問;由於uncore這些設備依賴於手頭的實際處理器,因此通過模型特定寄存器(MSR)訪問rdmsr(自然);

顯然,它們的工作流程是通過成對的寄存器完成的——1個寄存器組事件計數器計數,2個寄存器是計數器中的值;計數器可以配置為在一堆事件後遞增,而不僅僅是 1;+ 這些計數器中有一些中斷/技術注意到溢出;

  • 更多可以在 Intel 的“IA-32 Software Developer’s Manual Vol 3B”第 18 章“PERFORMANCE MONITORING”中找到;

uncore另外, “Architectural Performance Monitoring Version 1”版本(手冊中有1-4版本,我不知道哪個是我的處理器)的這些PMC的MSR格式在“圖18-1”中描述。 佈局IA32_PERFEVTSELx MSRs”(我的第 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(文件linux-source-3.13.0/include/uapi/linux/perf_event.h),它的主要部分可能是__u64 config欄位——它可以包含特定於 CPU 的事件定義(那些 Intel 圖中描述的格式中的 64 位字)或核心的事件

配置字的 MSB 表示其餘部分是否包含

$$ raw CPU’s or kernel’s event $$

核心事件定義為 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是我的別名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(files 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

我想知道coresHardware 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

是。

詳情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 eventHardware cache event

顯然,Hardware event來自英特爾所謂的“預定義架構性能事件”,18.2.1.2 in IA-32 Software Developer’s Manual Vol 3B。手冊的“18.1 性能監控概述”將它們描述為:

第二類性能監控能力稱為架構性能監控。此類支持相同的計數和基於中斷的事件採樣用法,但可用事件集較少。架構性能事件的可見行為在處理器實現中是一致的。使用 CPUID.0AH 列舉架構性能監控功能的可用性。這些事件在第 18.2 節中討論。

– 另一種類型是:

從 Intel Core Solo 和 Intel Core Duo 處理器開始,有兩類性能監控功能。第一類支持使用計數或基於中斷的事件採樣來監控性能的事件。這些事件是非架構性的,並且因處理器型號而異…

這些事件確實只是指向底層“原始”硬體事件的連結,可以通過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在“LLC Misses”的“表 18-1. 預定義架構性能事件的 UMask 和事件選擇編碼”中找到:

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 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] =
{...}

——沙橋應該是哪個?

其中之一 –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 */
   };
...

它們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和 not 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;
}

(因此,對於實用程序而言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同時管理多個事件的查詢的方式。

引用自:https://unix.stackexchange.com/questions/326621