我应该为 perf 的 -e 选项使用哪个事件来获取函数分支事件?
Which event should I use for -e option for perf to get function branch events?
我目前在我的 Nexus 5 中使用 simpleperf
,它是 Android 的 perf 的移植版本。我希望做的是动态获取本机函数的执行顺序。
我想应该有一种方法可以在发生分支事件时转储样本记录。所以我要做的就是执行simpleperf record -e branch-loads:u -p [pid]
.
下面我列出了我的设备支持的一些相关事件。为了我的目的,我尝试了 branch-loads
和 branch-instructions
。但他们都没有返回预期的结果。我相信这是由于分支包括功能以及条件跳转。
root@hammerhead:/data/local/tmp # ./simpleperf32 list
List of hw-cache events:
...
branch-loads
branch-load-misses
branch-stores
branch-store-misses
node-loads
node-load-misses
node-stores
node-store-misses
node-prefetches
node-prefetch-misses
List of hardware events:
cpu-cycles
instructions
branch-instructions
branch-misses
bus-cycles
stalled-cycles-frontend
stalled-cycles-backend
那么,我怎样才能只获得函数调用事件呢?或者,如果我走错了路,请指出正确的路。谢谢。
perf list
没有列出实际的硬件事件,它只是一个 perf-predefined 列表的列表,并且没有任何 CPU 完全支持。一些 CPUs 将几个事件映射到 perf 的预定义,其他映射不同的事件集。
您应该检查 CPU 核心 (qualcomm krait 400) 的文档以找到实际的硬件性能监控事件(计数器)并将它们用作原始数据(编码为 perf stat -e rXXXX
或 perf_attr 也是特定于体系结构的)。您也可以尝试 perf stat
/ perf stat -d
来检查某些默认列表中哪些事件被计算(支持)。
您的 nexus 5 基于 Krait 400 CPU 内核。
krait 中报告了一些问题:How to get perf_event results for 2nd Nexus7 with Krait CPU
并且有 link 补丁,为 krait 定义标准事件:
http://www.serverphorums.com/read.php?12,850329
有两组从预定义性能到实际硬件事件的映射。一个支持 branch-instructions
事件,另一个不支持:
/*
+ * Krait HW events mapping
+ */
+static const unsigned krait_perf_map[PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
+ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
+
+static const unsigned krait_perf_map_no_branch[PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
+ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
根据选择代码,这是Krait更高版本的特性CPU:
+static int krait_pmu_init(struct arm_pmu *cpu_pmu)
+{
+ u32 id = read_cpuid_id() & 0xffffff00;
+
+ armv7pmu_init(cpu_pmu);
+ cpu_pmu->name = "ARMv7 Krait";
+ /* Some early versions of Krait don't support PC write events */
+ if (id == 0x511f0400 || id == 0x510f0600)
+ cpu_pmu->map_event = krait_map_event_no_branch;
+ else
+ cpu_pmu->map_event = krait_map_event;
+ cpu_pmu->num_events = armv7_read_num_pmnc_events();
+ cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
+ return 0;
+}
我可以解码 cpuid - Krait 400 和 Krait 600 不支持分支指令 PMU 事件(PC 写入事件)。
更新:如果您的 Nexus 5x 使用 ARM Cortex A57 内核,则有原始事件列表,基于 "Table 11-24 from the "Cortex A57 技术参考手册""
https://sourceforge.net/p/perfmon2/libpfm4/ci/master/tree/lib/events/arm_cortex_a57_events.h
仍然没有所有分支机构的计数器。有 BRANCH_MISPRED 和 BRANCH_PRED 但我无法访问文档,也不知道它们是否会计算所有分支。
我目前在我的 Nexus 5 中使用 simpleperf
,它是 Android 的 perf 的移植版本。我希望做的是动态获取本机函数的执行顺序。
我想应该有一种方法可以在发生分支事件时转储样本记录。所以我要做的就是执行simpleperf record -e branch-loads:u -p [pid]
.
下面我列出了我的设备支持的一些相关事件。为了我的目的,我尝试了 branch-loads
和 branch-instructions
。但他们都没有返回预期的结果。我相信这是由于分支包括功能以及条件跳转。
root@hammerhead:/data/local/tmp # ./simpleperf32 list
List of hw-cache events:
...
branch-loads
branch-load-misses
branch-stores
branch-store-misses
node-loads
node-load-misses
node-stores
node-store-misses
node-prefetches
node-prefetch-misses
List of hardware events:
cpu-cycles
instructions
branch-instructions
branch-misses
bus-cycles
stalled-cycles-frontend
stalled-cycles-backend
那么,我怎样才能只获得函数调用事件呢?或者,如果我走错了路,请指出正确的路。谢谢。
perf list
没有列出实际的硬件事件,它只是一个 perf-predefined 列表的列表,并且没有任何 CPU 完全支持。一些 CPUs 将几个事件映射到 perf 的预定义,其他映射不同的事件集。
您应该检查 CPU 核心 (qualcomm krait 400) 的文档以找到实际的硬件性能监控事件(计数器)并将它们用作原始数据(编码为 perf stat -e rXXXX
或 perf_attr 也是特定于体系结构的)。您也可以尝试 perf stat
/ perf stat -d
来检查某些默认列表中哪些事件被计算(支持)。
您的 nexus 5 基于 Krait 400 CPU 内核。
krait 中报告了一些问题:How to get perf_event results for 2nd Nexus7 with Krait CPU 并且有 link 补丁,为 krait 定义标准事件:
http://www.serverphorums.com/read.php?12,850329
有两组从预定义性能到实际硬件事件的映射。一个支持 branch-instructions
事件,另一个不支持:
/*
+ * Krait HW events mapping
+ */
+static const unsigned krait_perf_map[PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
+ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
+
+static const unsigned krait_perf_map_no_branch[PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
+ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
根据选择代码,这是Krait更高版本的特性CPU:
+static int krait_pmu_init(struct arm_pmu *cpu_pmu)
+{
+ u32 id = read_cpuid_id() & 0xffffff00;
+
+ armv7pmu_init(cpu_pmu);
+ cpu_pmu->name = "ARMv7 Krait";
+ /* Some early versions of Krait don't support PC write events */
+ if (id == 0x511f0400 || id == 0x510f0600)
+ cpu_pmu->map_event = krait_map_event_no_branch;
+ else
+ cpu_pmu->map_event = krait_map_event;
+ cpu_pmu->num_events = armv7_read_num_pmnc_events();
+ cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
+ return 0;
+}
我可以解码 cpuid - Krait 400 和 Krait 600 不支持分支指令 PMU 事件(PC 写入事件)。
更新:如果您的 Nexus 5x 使用 ARM Cortex A57 内核,则有原始事件列表,基于 "Table 11-24 from the "Cortex A57 技术参考手册""
https://sourceforge.net/p/perfmon2/libpfm4/ci/master/tree/lib/events/arm_cortex_a57_events.h
仍然没有所有分支机构的计数器。有 BRANCH_MISPRED 和 BRANCH_PRED 但我无法访问文档,也不知道它们是否会计算所有分支。