CoreMark嵌入式处理器性能测试工具
安装、编译和测试
CoreMark是一个综合性基准测试程序,主要用于测量嵌入式系统中CPU的性能。其代码用C语言编写,主要执行列表操作(插入、删除、反转、排序等)、矩阵运算,简单状态机(扫描字符串进行状态转换,主要测试switch-case和if语句的行为),CRC运算(测试循环冗余校验运算和用于测试过程的自检)。CoreMark的测量结果为单一分值,衡量每秒种执行了多少次迭代,便于不同处理器之间分值的比较。
可以在github上获取coremark源码。
git clone https://github.com/eembc/coremark.git
在linux笔记本上直接编译,先测试一下电脑的性能。
cd coremark
make
# 编译完成后直接运行
./coremark.exe
电脑测试结果见下图。图中可以看出,笔者笔记本电脑每秒可以进行约23212次迭代,也即CoreMark的跑分结果。

测试嵌入式平台性能
手中有一块ITX-3588J开发板,将coremark源码拷贝到该平台上编译后测试,结果见下图。该平台的CPU型号是来自rockchip的rk3588,其测试分数为17435分左右。还是没有我这陈年老笔记本强的。当然,测试结果与编译器和指令集架构有关系,仅供参考。

perf性能分析工具
Perf是集成在Linux内核中的性能分析工具,从Linux内核2.6.31开始集成到内核中。Perf依赖硬件平台提供的硬件事件支持或者内核提供的软件事件支持,能够对CPU和操作系统性能相关的指标进行采样,用较低的开销收集运行时性能数据。后文介绍perf的安装方法和常用的命令。
perf安装
在终端中,使用如下命令,完成perf工具的安装:
sudo apt install linux-tools-common linux-tools-generic linux-tools-`uname -r`
perf list
perf list命令用来查看perf所支持的性能事件,包含软件和硬件两个方面。
sudo perf list hw
sudo perf list cache # hw和cache是CPU架构相关的事件,依赖于具体硬件
sudo perf list sw # sw实际上是内核的计数器,与硬件无关



perf stat
perf stat是处理器性能分析中用得最多的命令之一。以一个demo进行演示,代码如下。
/*
* Perf测试demo
* testPerf.cpp
*/
#include <iostream>
#include <cmath>
using namespace std;
void for_loop() {
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 10000; j++) {
int x = sin(i) + cos(j);
}
}
}
void loop_small() {
for (int i = 0; i < 10; i++) {
for_loop();
}
}
void loop_big() {
for (int i = 0; i < 100; i++) {
for_loop();
}
}
int main() {
loop_big();
loop_small();
return 0;
}
编译demo代码,使用perf stat命令对上述程序进行性能测试。
g++ testPerf.cpp -o testPerf
sudo perf stat ./testPerf
测试结果如下图。根据图中结果,testPerf程序执行了约63秒,共执行了322706077907个指令,时钟周期数目为197826310383,IPC值为1.63。cpu-migrations表示在不同的cpu核心间调度了11次,context-switches表示该进程发生了330次上下文切换。branch-misses表示分支误预测率为0.65%。最下方显示了进程在用户态和核心态的运行时长。
IPC,Instructions Per Cycle,每个时钟周期平均执行的指令数。可以用来衡量处理器性能。

perf record && perf report
perf record可以将性能数据记录到当前目录下的perf.data,随后使用perf report命令,从perf record命令产生的perf.data文件中读取采样的性能数据,分析记录数据并把剖析的信息以用户可读的方式显示出来。
以testPerf程序为例,分别运行perf record和perf report命令进行效果测试,结果如下图所示。由分析结果可以清晰地看到,在cpu-clock一项事件中,每个函数在进程生命周期内占用CPU时间的比例是多少,后续可以根据perf.data来生成火焰图,更直观地查看热点函数。
sudo perf record -e cpu-clock ./testPerf # -e 选项后面跟具体的事件
# 具体用法可以使用 sudo perf record --help来查看
sudo perf report


perf report产生的分析结果可以进行交互,例如查看for_loop函数的汇编代码。Perf在采样过程中,会根据PID等数据定位相应的进程,按照指令地址PC和可执行与可链接格式(ELF)文件中的符号表定位产生PCI中断的指令所属函数。(具体的perf工具原理可以阅读参考文献[2]中perf性能分析工具一节)

FlameGraph火焰图绘制工具
工具安装
可以在github上下载FlameGraph火焰图绘制工具源码。
git clone https://github.com/brendangregg/FlameGraph.git
火焰图生成示例
以testPerf为例,生成testPerf程序的火焰图。
sudo perf record -g -e cpu-clock ./testPerf #需要添加-g选项,保存函数调用栈等信息,因为火焰图是基于stack信息来生成的。
sudo perf script -i perf.data > out.perf
${FlameGraph源码路径}/stackcollapse-perf.pl out.perf > out.floded
${FlameGraph源码路径}/flamegraph.pl out.floded > cp.svg
cp.svg即为最后生成的火焰图,见下图。建议使用浏览器打开,可以通过点击方式与火焰图进行交互。通过火焰图也可以直观看出整个进程中的热点函数。

需要特别注意的是,火焰图y轴表示调用栈,每一导都是一个函数,调用栈越深,火焰图越高。每个函数下方是其父函数。x轴表示抽样,如果一个函数在x轴占据的宽度越宽,表示所有抽样中,为此函数的次数越多,也即执行的时间更长。x轴不代表时间,但能反映一个函数的执行时间。
参考文献
[2] 计算机体系结构基础 第3版 胡伟武等著
本文地址: Linux环境编程性能测试和分析