1. 基于编译器优化选项的代码性能对比
任务目标
编写一个计算密集型的基准测试程序,分别在 -O0、-O2、-Os 三个优化级别下交叉编译,测量程序执行时间并查看生成二进制文件的大小,从而直观理解编译器优化对嵌入式系统性能与资源占用的影响。
环境与依赖
- 宿主机:Linux(或WSL)
- 交叉编译器:
arm-none-eabi-gcc(或本机gcc直接验证) - 计时工具:
time命令(或开发板上的硬件定时器)
基准测试程序
以下代码执行多次整数乘加运算与循环移位操作,模拟嵌入式中常见的滤波/校验计算负载。程序通过宏 LOOPS 控制总计算量,保证在 -O0 下也有可观测的执行时间。
编译与运行
使用 arm-none-eabi-gcc 时,编译命令如下(若为本机验证,将前缀替换为 gcc 即可):
验证方法与判定标准
- 代码大小对比:执行
arm-none-eabi-size后,观察text段大小。预期-O0最大,-Os最小,-O2介于两者之间或接近-Os。 - 执行时间对比:在开发板上用定时器测量三个版本从调用
compute()到返回的耗时(本机验证可用time命令)。预期-O0耗时最长,-O2明显缩短,-Os与-O2相当或略慢。 - 结果一致性:三个版本打印的
Result值必须完全相同(均为0x8F4d1B2A),以确认优化未改变程序语义。
若三个版本输出相同结果,且 -O2/-Os 的代码段明显小于 -O0、执行时间明显短于 -O0,则本案例验证通过。
常见问题
- volatile 的作用:循环计数器声明为
volatile int,防止编译器在-O2/-Os下将整个循环优化掉(因为循环次数固定且无副作用时,编译器可能直接计算结果)。 - 结果一致性验证:若三个版本输出不同,说明优化引入了未定义行为(如整数溢出依赖),需检查代码。
- 嵌入式环境差异:在开发板上测量时,建议使用
DWT->CYCCNT寄存器或专用定时器,避免printf耗时影响测量。