一次把编译器优化痕迹扒光的实战笔记

举报
i-WIFI 发表于 2025/07/26 14:16:35 2025/07/26
【摘要】 背景前阵子给自研的 DSL(领域规则引擎)做二期性能优化,目标:同样的业务脚本,CPU 下降 30 %,内存下降 20 %,还不能动业务代码。于是我把整个编译链从 .rule 文本一路跟到机器码,边踩坑边记笔记。今天把最硬核的四段链路拆开聊:词法分析、语法分析、中间表示、编译器优化。所有数字来自线上火焰图 + perf stat,表格里是我手撸的对比,放心食用。 1. 词法分析:少写一行正则...

背景
前阵子给自研的 DSL(领域规则引擎)做二期性能优化,目标:同样的业务脚本,CPU 下降 30 %,内存下降 20 %,还不能动业务代码。于是我把整个编译链从 .rule 文本一路跟到机器码,边踩坑边记笔记。今天把最硬核的四段链路拆开聊:词法分析、语法分析、中间表示、编译器优化。所有数字来自线上火焰图 + perf stat,表格里是我手撸的对比,放心食用。


1. 词法分析:少写一行正则,能省 11 % 的 token 耗时

我们最早用 Flex 生成词法器,.l 文件里塞了 180 条正则,结果在 2 MB 脚本上 tokenize 一次 42 ms,火焰图里 yy_match 一路飘红。

写法 状态机大小 tokenize 耗时 备注
纯正则 2.8 MB 42 ms 回退多到爆炸
手写 DFA + 关键字表 0.4 MB 31 ms 11 % CPU 收益

改法:
把关键字提前放进一个 constexpr phf(完美哈希),正则只负责标识符/字面量。重新生成状态机后,cache miss 降了一半。
血泪提示:“写词法规则时,先把关键字抠出来,再给 Flex 喂剩下的面包屑。”


2. 语法分析:LALR(1) 看起来美好,GLR 救我狗命

Flex 之后接的是 Bison(LALR(1))。业务方给了一段嵌套三元表达式:

cond ? a > b ? x : y : z

Bison 直接 shift/reduce 冲突 17 处。人肉改写优先级后,规约动作里偷偷加了 4 个临时节点,AST 节点暴涨 20 %,GC 抖动肉眼可见。

解析器 冲突数 AST 节点数 GC 次数/万次请求
LALR(1) 17 1.2 ×源码节点 38
GLR 0 1.0 ×源码节点 21

切到 GLR(GNU Bison --glr-parser)后,冲突消失,AST 零膨胀,GC 次数直接砍半。代价是解析器二进制从 600 KB 涨到 1.1 MB,但内存省得更多,老板拍板:“加这点体积不叫事”。


3. 中间表示:SSA 不是银弹,但能让 LICM 肉眼可见

AST → LLVM IR 阶段,我们先把 DSL 翻译成自定义的高阶 IR,再 llc 到 LLVM SSA。
最初为了省事,IR 里保留了大量 if(cond) { ... } 的抽象语法糖,结果 LICM(Loop-Invariant Code Motion)失效,循环里每次都在算同一个 strlen

版本 IR 形式 循环内指令数 优化后 CPU
高阶 IR 带语法糖 112 100 % 基线
SSA IR φ-node + basic block 73 82 % 基线

把高阶 IR 降成 SSA 后,LICM 把 39 条循环不变指令一次性提到 preheader,压测 P99 从 4.3 ms 跌到 3.5 ms。
结论:“别让抽象语法挡住优化器视线,SSA 再丑也得上。”


4. 编译器优化:一行 restrict,指令数少 15 %

最后一步,LLVM 后端开 -O3 -march=native。我们手动在 DSL 生成的 C++ 代码里插了一个 __restrict,告诉优化器“指针绝不 alias”。结果:

编译参数 指令数/函数 循环展开次数 L1 miss
-O2 228 0 3.2 %
-O3 214 2 2.8 %
-O3 + restrict 183 4 1.9 %

15 % 指令数下降直接体现在线上:CPU 从 85 % 降到 62 %,老板终于满意。


5. 完整链路耗时 & CPU 分布

clang -ftime-trace 抓了一次全量编译:

阶段 用时(ms) 占用百分比 关键瓶颈
词法分析 31 7 % 正则回退
语法分析 48 11 % GLR 回溯
语义检查+IR 生成 92 21 % 类型推导
LLVM 优化 188 42 % 矢量分析
后端 codegen 85 19 % 寄存器分配

6. 经验打包带走

  • 词法:关键字提前哈希,状态机越小越香。
  • 语法:LALR(1) 冲突多就果断上 GLR,别让 AST 膨胀。
  • IR:尽早降到 SSA,让循环优化器有活干。
  • 后端:能加 restrict 就别害羞,指针别名是优化天敌。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。