简介:
我们在开发过程中,难免会遇到些某些代码cpu占用率比较高长时间占用cpus,造成的其他任务响应不及时的性能问题,我们如何评估某段代码占用的cpu时间,可以使用perf_counter这个开源工具。perf_counter 是一个基于ARM CORTEX-M 架构下,利用SysTick 特性在不影响系统运行的前提下,实现系统延时、性能评估,支持RTOS(freertos/rt-thread/threadx)以及逻辑环境下使用,对应的开源工程路径如下,https://github.com/GorgonMeducer/perf_counter
perf_counter 移植适配
除了上述说的可以用于计算某段代码执行所占用的cpu cycel 信息功能外,perf_counter 以下特性可供用户使用,其他的时间的delay 及内部提供的宏函数功能也都是我们经常在开发中用到的,其功能还是很丰富的,从描述可知已经支持了freertos,我们在freertos 基础上来验证,最新版本对应 Features 描述如下。
perf_counter 的移植过程说明如下,按照这个裸机下的流程我们在freertos 上也可以按照该流程适配即可。
step1 添加文件至工程
perf_counter 源文件中还有perf_port_pmu.c 相关的函数,pmu 对应的是armv8.1-m 架构的特性,本次实验的芯片为M7 是armv7-m架构,该文件不适用,不加入工程编译即可。
PMU 功能及使用描述如下:
step2 对接systick 回调函数
根据上述移植过程的第6步,需要在systick 的中断接口内 调用perfc_port_insert_to_system_timer_insert_ovf_handler 接口,在freertos 系统中有对应的回调hook 宏定义,对应定义如下,tick hook 函数中调用该接口。
之后在main函数中追加perf_counter 初始化处理即可完成移植适配。
烧写验证
添加如下测试代码验证测试 vTaskDelay(1000) 占用cpu cycle数量。
start_cycle_counter(); vTaskDelay(1000); int64_t lCycleUsed = stop_cycle_counter(); printf("cycle counter %lld.\r\n",lCycleUsed);
计算结果如下
STM32H7S7 配置的CPU 主频为600MHZ
1/600 000 000 (S) * 599823355(cycle) = 0.9997055916666667(S)
计算结果和1S 误差很小了,完全可以用来评估某段代码所占用的cpu cycle.
移植好了之后我们使用perf_counter 测量下使用CPU 搬运一帧数据和使用DMA2D 搬运时性能。
在LVGL 底层刷写Framebuff 使用cpu 搬运数据时添加如下测试代码。
使用DMA2D 搬运数据时添加如下测试代码。
DMA2D搬运一屏幕数据验证结果如下:
[2024-09-28 14:15:04.531] dma2d x1 0 y1 0 x2 799 y2 479 cycle counter 5467414. [2024-09-28 14:15:04.563] dma2d x1 0 y1 0 x2 799 y2 479 cycle counter 5467754. [2024-09-28 14:15:04.689] dma2d x1 0 y1 0 x2 799 y2 479 cycle counter 5530512. [2024-09-28 14:15:04.800] dma2d x1 0 y1 0 x2 799 y2 479 cycle counter 5530574. [2024-09-28 14:15:04.908] dma2d x1 0 y1 0 x2 799 y2 479 cycle counter 5468813. [2024-09-28 14:15:05.014] dma2d x1 0 y1 0 x2 799 y2 479 cycle counter 5530925. [2024-09-28 14:15:05.119] dma2d x1 0 y1 0 x2 799 y2 479 cycle counter 5468605. [2024-09-28 14:15:05.214] dma2d x1 0 y1 0 x2 799 y2 479 cycle counter 5530689. [2024-09-28 14:15:17.625] dma2d x1 0 y1 0 x2 799 y2 479 cycle counter 5530455. [2024-09-28 14:15:17.625] dma2d x1 0 y1 0 x2 799 y2 479 cycle counter 5522413.
CPU搬运一屏幕数据验证结果如下:
[2024-09-28 14:18:53.243] cpu x1 0 y1 0 x2 799 y2 479 cycle counter 16401524. [2024-09-28 14:18:53.286] cpu x1 0 y1 0 x2 799 y2 479 cycle counter 16444113. [2024-09-28 14:18:53.331] cpu x1 0 y1 0 x2 799 y2 479 cycle counter 16342313. [2024-09-28 14:18:53.375] cpu x1 0 y1 0 x2 799 y2 479 cycle counter 16361931. [2024-09-28 14:18:53.419] cpu x1 0 y1 0 x2 799 y2 479 cycle counter 16535207. [2024-09-28 14:18:53.493] cpu x1 0 y1 0 x2 799 y2 479 cycle counter 16395806. [2024-09-28 14:18:53.541] cpu x1 0 y1 0 x2 799 y2 479 cycle counter 16484525. [2024-09-28 14:18:53.581] cpu x1 0 y1 0 x2 799 y2 479 cycle counter 16349565. [2024-09-28 14:18:53.627] cpu x1 0 y1 0 x2 799 y2 479 cycle counter 16360293. [2024-09-28 14:18:53.669] cpu x1 0 y1 0 x2 799 y2 479 cycle counter 16494751. [2024-09-28 14:18:53.712] cpu x1 0 y1 0 x2 799 y2 479 cycle counter 16435455. [2024-09-28 14:18:53.761] cpu x1 0 y1 0 x2 799 y2 479 cycle counter 16357431. [2024-09-28 14:18:53.808] cpu x1 0 y1 0 x2 799 y2 479 cycle counter 16413555.
从上述数据可以看出使用DMA2D搬运一屏幕数据大约5530925 个cpu cycle 600Mhz 的主频大约9.2182ms,CPU搬运一屏幕数据大约16401524 个cpu cycle 600Mhz 的主频大约27.3358ms ,可以看出DMA2D的搬运数据的效率是CPU的3倍左右。