原创 缩小编译代码 size 的几种方式

2010-5-12 15:00 3657 8 12 分类: 消费电子

缩小编译代码 size 的几种方式

 

目标:

工作在 mcu world, 我们需要不断致力于, size speed 上对编译的code 进行优化. 这是 firmware engineer windows world 的同行, 最显著的不同点之一. 构建Fimware目标包括: (1) 尽量降低最终编译的code size, 我们不断降低product cost, 同时降低mcu 的功耗. (2) 尽量提高 code speed, 我们不断接近现场的, 实时的应用.

往往两者的追求目的相互矛盾, 常见的现象是: 我们优化的过程, 一方面增加了 project compile 的时间, 另一方面, size 或是 speed 的二选一的目标的提升, 往往会导致两者中另外一者的(性能表现的)降低. 但这也并不绝对, 如大多数编译器的参考文档中, 可能说明, speed 的优化, 甚至有可能带来 size 的缩小. 这个 topic, 就不是本文讨论的问题了.

此外, 本文中提及的各种方式, 如果没有特别指出, 则均为对arm code 的讨论.

 

限制:

文中说明的几种缩小编译代码 size 的方式, 来源于:

(1) ARM C/C++ Compiler Reference Guide, 而该文档, 伴随IDE共同发布.

为简化起见, 我们在之后的讨论中, 将该文档统称为 reference.

并且在本文中, 作者不会在每一处对两个来源进行标识.

(2) Allen 自己的工作实践;

 

As we know, 每个用于降低 code size method 进行仔细诠释, 都是一个可以拓展的专题讨论. 限于作者的实际工作水平, 以及紧张的工作 schedule, 我们不会去展开专题去 dicuss know-why.

但是, 作者仍然相信, 本文会帮助新进入的同行, project 的开始阶段, 就遵循这些基本的 rules coding. 而这将大大降低, 未来重新 review whole project 的压力.

 

环境:

Topic 中的实现环境, 大多在 arm7 mcu 下进行验证, 编译器使用 IAR. 同时 chip MAM 需要开启(源于我们的工作经验, MAM未开启将导致code 片段的执行异常).

 

缩小编译代码 size 的几种方式:

(A)    逻辑与算法:

合理的工作逻辑与算法. 一般而言, Code 永远是工程师的逻辑思维的体现. 无论是实现 function target or 构建 system struction, 逻辑思维的能力高低, code size 具有深度影响(甚至对整个 project 的成功实现, 具有决定性的影响).

 

(B) 编译器的配置:

1. 将编译器的 size 优化调整到 high级别.

2.   如果我们是 arm user, 应选择 Thumb mode, 而不是 Arm mode.

我们无意在这里讨论16-bit thumb指令集 32-bit arm 指令集有何具体异同. 我们仅仅从 mcu datasheet 中寻找到如下解释(讨论了两者最终表现力): “工作在与 arm mode 相同的 32-bit 寄存器上, thumb code 保持了绝大部分的 arm 的表现力(的同时), Thumb code能够提供高达 65% (作为比较的)arm code size.”

 

(C) 谨慎使用任何标准/编译器提供的 C Library function:

谨慎使用编译器提供的任何C Library function, 如果必需, 尽量自行完成需要的函数功能.

1. 谨慎使用string相关函数

无论是 sprintf(), atoi(), ntop(),都会带来size 的显著增加. 如有可能, 我们应当自行完成我们需要的类似的 functions.

 

2. 谨慎使用 time 相关函数: 举例说 localtime(), etc 等函数.

 

3.   谨慎使用 math 函数, 尽量不要包含 math.h
作为两个比较的的例子是, 在同等编译条件下, fasbs()可能多耗费 about 200bytes. sqrt() 可能会多耗费 about 3.5k bytes.

 

(D) 数据类型与编程习惯

1.       尽量避免 char(U8/S8), short(U16/S16) 的定义, 而使用 int(U32/S32) 的定义.

对于从 8-bit来到 arm world engineer, 可能份外不习惯这个转变吧?

C/C++ compiler reference document 明确指出: 只要可能, 就应使用 int or long 来替代 char or short, 从而避免了符号位扩展与zero拓展. 而且, loop index 使用 int/long 将减小 code 产生. 特别要指出, thumb mode, stack pointer(SP) 被严格定义为 32-bit data types(因此更应该使用 int/long).

       一个令人有兴趣的简单实验能够证明, 所谓的”sign extension or zero extensize”带来的额外代码消耗. 在一份c的源文件中, 如果我们定义了 U8 global_data. 简单将其改为 U32 global_data. Then do rebuild all, we will find the code size decrease 4 bytes… ; ) 但是要提及的是, 我们的项目经验说明这个way往往还会带来一个其他的效果: DATA size在这种情形下或略有增加.

 

2.       尽量避免使用带符号位的数据类型.

 

3.       尽量避免 long(8-byte) 的定义.

 

4.       Bitfields packed structures 将产生大而且慢的代码.

对于 packed structures, 作者在相同的 blog 主页发表了专题文章, 指出了选择使用 packed structures, 仍然可以享受到尽可能小的 code size, 以及保持access speed的处理方式. 检索作者的 blog, 或检查全部文章列表, 将会发现该篇文章. 在我们的项目经验中, 32k bytes 左右的 project , 我们获得了额外的大约 2k bytes 的节省的 code size.

 

5.       尽量不要定义 float, double.

在一些运算中, 我们常常将牵涉到如下步骤: float *10e(小数点后位数), float转化为U32进行运算. 结果在/10e(相应位数). 运算精度在这里被降低了. 但这完全取决于我们的工作目标: 在不复杂的算法中, 避免了浮点运算的使用(以上讨论, 均假设我们的 mcu 不包含浮点运算协处理器). Reference 也一再强调没有math协处理器, 浮点数据类型效率低下.

 

6.       reference 指出, 尽量定义 local 变量. 减少 static global 变量的定义, 这样将帮助优化的过程. local 变量尽量少使用 &. Reference 指出, 这种定义将放置变量到 memory , 而不能放置到处理器的 register (代码会变大变慢). 另外也不能有助于优化器进行优化.

 

7.       *(2的倍数), /(2的倍数), 使用 “<<” 以及 “>>” 操作.

 

8.   应保持数据变量的type 定义的一致性, 在运算中, 尽量减少类似 U32 -> U16 -> U32 的不必要的强制转化过程.

 

9.   定义字符串为全局变量, ram 富余的情况下, 这是一个利用 ram 来分担降低 code size 的技巧.

构建代码的过程, 不仅仅是理性思维落实为真实世界逻辑的过程, 我们觉得, 也是和编译器进行交互的过程. 我们所作所为, 需要实现目的之逻辑, 我觉得也需要, "讨好"编译器, 让它为我们的代码, 生产 size 和 speed 都得到优化的job.
 

Allen

GV-TECH

 

PARTNER CONTENT

文章评论4条评论)

登录后参与讨论

用户1532209 2010-5-14 14:51

感谢经验分享!

用户1238434 2010-5-14 11:33

不错,说的非常好! 我来补充一下: 1.了解汇编器和汇编指令。 2.注意循环的使用,特别是循环嵌套的使用,这对SIZE和SPEED都很重要。 3.注意逻辑的表达,避免重复。 4.选择合理的数据结构。 5.选择更好的算法。

用户1537136 2010-5-13 11:38

高手啊!学习了!

用户1277994 2010-5-12 18:57

多谢博主allen的分享!
相关推荐阅读
allen_zhan 2023-02-27 19:08
对"三极管"译名由来的探讨
想讨论一个有意思的话题:今天中国大陆的电子业界, 为何将 BJT 称呼为 "三极管"? 或因其象形, 前辈自行进行随意的不严谨定义么? 带着疑问我们做了一下延伸查阅, 或得出这样的结论, 即中译名"三...
allen_zhan 2023-02-19 18:15
对知乎提问"为何三极管的一个PN结工作在反偏"的回复
将这个回复, 也发表在博文中, 作为自己的一个学习笔记叭.知乎问题: "三极管里面的PN结相当于二极管,为什么里面PN结加反向电压也能导通?"我的回复:首先, 二极管的"反向"概念, 容易给初学者某种...
allen_zhan 2023-02-18 10:17
从肖特基二极管到PN结与三极管
最近数个工作日的兴趣是回顾电子基础器件的发明/发展历史, 期待夯实技术基础的底蕴. 在学习与搜索资料的过程中, 顺便对知乎的一个同学的基础问题, 进行了回复. 不小心回复一下就成了千字文, 觉得挺有趣...
allen_zhan 2023-01-28 11:53
微功率 ISM 频率探讨相关文档组总结
不知不觉, 自开启关于微功率频率的话题起, 即从第一份文章写就到今天总结之日, 已经接近 10 个工作日左右. 早先的想法是对工程界未来的微功率设备相关项目, 从项目规划开始, 对选择系统, 频率, ...
allen_zhan 2023-01-27 22:50
关于 LoRa 应用场景的讨论
说明: 本文中斜体部分表示来自公告文件的部分内容剪贴或合并整理.1. "第52号文" 对 470MHz 的约束引自 如下:(四)民用计量仪表限在建筑楼宇、住宅小区及村庄等小范围内组网应用,任意时刻限...
allen_zhan 2023-01-25 13:24
ISM 频段中 2.4G 与 5.8GHz 设备的使用与限制
说明: 本文中斜体部分表示来自公告文件的部分内容剪贴或合并整理.1. ISM 频段定义中的 2.4G 与 5.8GHz正如同 文中确定的, 2.4G, 5.8GHz 属于中国大陆 ISM 频段的定义...
EE直播间
更多
我要评论
4
8
关闭 站长推荐上一条 /3 下一条