找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1823

积分

0

好友

238

主题
发表于 6 天前 | 查看: 18| 回复: 0

工欲善其事,必先利其器。对于嵌入式工程师而言,嵌入式编译器是不可或缺的核心工具,常被称为“C语言翻译官”。由于C语言历史悠久且早期缺乏统一规范,加上计算机产业早期的拓荒特性,市场上涌现了多种C语言编译器。

根据相关调研,嵌入式工程师较为青睐的编译器主要包括Keil(ArmCC)、IAR、GCC、AVR GCC、CLion、Clang、Green Hills、TI的CSS以及ADI的Visual DSP++等。随着嵌入式开发格局的逐渐稳固,Keil、IAR与GCC已形成三足鼎立之势,覆盖了绝大部分嵌入式产品的开发。尤其是GCC,作为一个完全开源的编译器,它被众多MCU厂商作为基础,改写成自家的集成开发环境(IDE)。然而,近来业界出现了一种声音,认为“开源才是最贵的”,暗示这些开源编译器背后可能隐藏着诸多隐形成本。

彩色装饰条 RTOS场景下,GCC性能不及IAR? 彩色装饰条

当前,“C/C++与RTOS结合使用”已成为嵌入式软件开发的黄金范式。因此,在嵌入式领域评判一个编译器是否“好用”,其在RTOS上的表现是关键指标。

根据知名嵌入式专家Jacob Beningo的测试,在使用RTOS时,IAR编译器编译出的代码性能指标通常显著优于GCC。尽管具体的公制测试结果有所差异,但IAR的优势普遍在20%到40%之间。以下是一组示例结果,该结果以IAR的指标除以ThreadX(Eclipse ThreadX)在GCC下的指标得出:

  • RTOS测试:ThreadX
  • 基准测试:74%
  • 系统调度:3%
  • 内存分配测试:28%
  • 消息处理:41%
  • 抢占式调度:19%
  • 同步处理:32%

或许有人会质疑,代码的编写质量才是决定性能的根本。此话不假,开发者确实可以通过投入大量时间对代码进行精细优化来提升性能,但这无疑意味着更长的开发周期和更高的开发成本。

例如,一些工期紧张的物联网(IoT)项目,若未及时进行代码优化,使用GCC可能导致处理时间增加20%,进而加剧电池消耗。又或者,GCC编译出的代码体积可能更大,迫使产品需要从120MHz升级到200MHz的MCU以容纳代码,这区区几块钱的芯片成本差异,却可能导致整体产品成本大幅攀升。

GCC无疑是行业的福音,但相比于商业编译器,它或许本身就伴随着额外的、隐性的开销。目前,许多RTOS,尤其是开源RTOS,通常只附带支持GCC的工具链,而不支持IAR等商业编译器,这在一定程度上限制了开发者的选择范围。

彩色装饰条 Keil编译出的文件体积,比GCC更小 彩色装饰条

尽管Keil提供了包含全免费教育版在内的多个版本,且针对STM32等主流MCU开发是免费的,但在进行某些深度开发时,Keil本身仍属于需要付费的商业编译器范畴。

在工程师社群中,经常能听到关于Keil的ArmCC编译器表现“神奇”的讨论。实际情况究竟如何?

根据一些工程师的实际测试,在开启多线程编译的前提下(对比对象包括Keil和VisualGDB),GCC的编译速度最快。然而,生成的可执行文件(bin)体积最小的则是ArmCC V5(代码执行效率未在此次测试中对比)。进一步对比ArmCC V5和V6,两者编译用时相差不大,可视为误差范围,但V5生成的bin文件体积比V6小得多。

优化选项 O0 O1 O2 O3 Ofast Os Oz
ARMCC V6.9 bin大小(KB) 131.13 90.03 95.54 98.54 97.45 87.84kB 85.47
编译用时(秒) 7.23 7.52 7.99 8.3 8.4 8.17 7.64
ARMCC V5.06 bin大小(KB) 77.18 64.49 61.19 61.44 - - - - - -
编译用时(秒) 7.93 8.25 8.15 9.68 - - - - - -
GCC 7.2 bin大小(KB) 176 135 136 144 - - 129 - -
编译用时(秒) 3.49 3.63 3.68 4.12 - - 3.96 - -

为何不同编译器产生的文件大小会有如此差异?有工程师曾遇到过GCC编译的bin文件比ArmCC大的情况,通过梳理代码发现,部分芯片原厂提供的底层代码已针对特定编译器做了优化,这实际上为工程师节省了自行优化的时间。

也有观点认为,Keil与GCC各有优势,通常难以兼得:Keil(ArmCC)对Arm芯片有天然优势,在代码执行效率和尺寸上表现更佳;而GCC的优势在于开源,给予开发者更大的定制和探索空间。

更有工程师在Cortex-M0内核上进行了实验,使用相同代码触发PendSV中断,测得ArmCC的响应时间为68个时钟周期,而GCC则为78个时钟周期。该工程师表示,尽管ArmCC不开源、不免费且不可控,但其生成的代码执行效率确实更高。

ArmCC编译器下的PendSV中断响应汇编代码
ArmCC中断响应汇编

GCC编译器下的PendSV中断响应汇编代码
GCC中断响应汇编

彩色装饰条 工程师的选择:各持己见,适者为佳 彩色装饰条

正所谓萝卜青菜各有所爱。无论测试数据如何,工程师们总有自己偏好的工具。这往往源于公司项目的不同需求——对Flash大小、执行速度、交付周期的要求各异,导致不同编译器的适用性结果也不同。

  • Keil支持者:在实际体验中,AC6版本的“Osize”优化效果非常显著,虽然性能可能略弱一丝,但生成的代码体积特别小,其他编译器难以匹敌,相同程序可比GCC小四分之一。不过Keil也让人“又爱又恨”,例如MDK AC6曾出现调试时光标乱跳的问题(商业版有所改善),或者经常将if-else结构优化成IT汇编指令,导致在反汇编窗口中设置的断点命中却未实际执行。不少用户表示,已经习惯了。
  • IAR青睐者:认为IAR不仅比Keil便宜不少,而且内置了MISRA静态检查工具,使用起来非常方便。
  • GCC传统派:青睐GCC+GDB调试配合VSCode编辑,在Linux系统下编译体验流畅。在某些对Flash容量不敏感的项目中,这能带来最快的交付速度。
  • 新锐工具派:也有工程师转向Clion、Clang等更现代的工具链。

那么,你如何看待不同编译器之间的这些差异?在实际的嵌入式开发项目中,你又会如何做出选择?

参考文献

[1] https://www.embedded.com/the-hidden-costs-of-open-source-compilers
[2] https://www.zhihu.com/question/26864086/answer/280900095
[3] https://club.rt-thread.org/ask/article/866813c0a2efd608.html
[4] https://www.bilibili.com/video/BV18h4y1v7yR


在技术选型的道路上,没有绝对的“最好”,只有最适合当前项目需求的“更好”。希望本文的对比能为你提供有价值的参考。如果你对嵌入式开发编译器原理有更深入的兴趣,欢迎在云栈社区与更多开发者交流探讨。




上一篇:Benchmark合伙人解读AI投资:为何押注Manus与Cursor,硅谷为何无法被取代
下一篇:CSS多列等高布局的演变:从8年JS补丁到Flexbox/Grid原生方案
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-10 09:02 , Processed in 0.325096 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表