我应该使用哪个事件for -e选项来获取函数分支事件?

时间:2016-09-28 07:49:28

标签: android kernel perf

我目前在我的Nexus 5中使用simpleperf,这是Android的perf的移植版本。我希望做的是动态获取原生函数'执行顺序。

我想应该有一种方法可以在有分支事件时转储样本记录。所以我要做的就是执行simpleperf record -e branch-loads:u -p [pid]

下面我列出了我的设备支持的一些相关事件。为了我的目的,我尝试了branch-loadsbranch-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

那么,我怎么才能获得函数调用事件呢?或者,如果我的方向错误,请指出正确的方法。感谢。

1 个答案:

答案 0 :(得分:2)

perf list没有列出实际的硬件事件,它只是一个perf预定义列表的列表,并且任何CPU都不完全支持它。有些CPU将几个事件映射到perf的预定义,其他地图不同的事件集。

您应该检查CPU内核的文档(qualcomm krait 400)以查找实际的硬件性能监视事件(计数器)并将它们用作原始(编码到perf stat -e rXXXX或在perf_attr中的RAW也是特定于体系结构)。您也可以尝试perf stat / perf stat -d来检查哪些事件是从某些默认列表中计算(支持)的。

您的nexus 5基于Krait 400 CPU核心。

在海峡报道了一些问题:How to get perf_event results for 2nd Nexus7 with Krait CPU 并且有补丁的链接,为krait定义标准事件:

http://www.serverphorums.com/read.php?12,850329

从预定义的perf到实际的hw事件有两组映射。一个支持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内核,则会有基于“Cortex A57技术参考手册”表11-24中的原始事件列表“

https://sourceforge.net/p/perfmon2/libpfm4/ci/master/tree/lib/events/arm_cortex_a57_events.h

仍然没有所有分支的反击。有BRANCH_MISPRED& BRANCH_PRED但我无法访问文档,也不知道他们是否会计算所有分支。