我应该使用哪个事件来执行perf函数以获取函数分支事件?

问题描述:

我目前在我的Nexus 5中使用了simpleperf,这是一个用于Android的perf的移植版本。我希望做的是动态获取本机函数的执行顺序。我应该使用哪个事件来执行perf函数以获取函数分支事件?

我想应该有一种方法来转储一个示例记录一旦有分支事件。所以我要做的就是执行simpleperf record -e branch-loads:u -p [pid]

下面我列出了一些在我的设备中支持的相关事件。我为我的目的尝试了branch-loadsbranch-instructions。但他们都没有返回预期的结果。我相信这是由于分支包括函数以及有条件的跳转。

[email protected]:/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 

那么,我怎样才能获得函数调用事件?或者如果我的方式不对,请给我指出正确的一条。谢谢。

+0

要获得完整的“本机函数”执行顺序“,您应该尝试跟踪,而不是像perf那样进行统计分析。 – osgx

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

您应该检查CPU核心(Qualcomm krait 400)的文档以查找实际的硬件性能监视事件(计数器)并将它们用作原始数据(编码为perf stat -e rXXXX或在perf_attr中编码为特定体系结构)。您也可以尝试使用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的实际硬件事件。一个与支持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 - 金环蛇400和金环蛇600不支持分支指令PMU事件(PC写入事件)。

更新:为了您的Nexus 5倍,如果它使用的ARM Cortex A57核心,有“从表11-24‘的Cortex A57技术参考手册’,”

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

原始事件的列表,基于

所有分行仍然没有柜台。有BRANCH_MISPRED & BRANCH_PRED,但我无法访问文档,不知道他们是否会统计所有分支。

+0

也未在libpfm4中列出:https://sourceforge.net/p/perfmon2/libpfm4/ci/master/tree/lib/events/arm_qcom_krait_events.h – osgx

+0

谢谢。由于Krait对ARM CoreSight的不良支持,我放弃了Nexus 5。相反,我尝试了具有Coretex A57 CPU的Neuxs 5x。但同样的问题发生了。不确定我是否以正确的方式进行测试。 – colordancer

+1

colordancer,A57没有所有分支计数的性能事件:https://sourceforge.net/p/perfmon2/libpfm4/ci/master/tree/lib/events/arm_cortex_a57_events.h但是有BRANCH_MISPRED和BRANCH_PRED事件,你应检查“Cortex A57技术参考手册”中的表11-24“并尝试将它们编码为perf的原始事件 – osgx