我用三种方式写了个软件,结果Rust一句话让我顿悟:我之前二十年,白干了!
作者:杰弗里·伦尼(Jeffrey Rennie) (一个搞PDF文档的程序员大叔,头发可能不多,但脑子贼灵)
大家好,我是个专门“折腾PDF”的程序员。你别看PDF现在人人会用,点一下“打印为PDF”就完事了,但背后可复杂了,复杂到什么程度?——它的说明书有756页!比你语文课本还厚!里面还得懂图片压缩、字体解码、各种加密……简直像在拆一颗定时炸弹。
但今天咱不讲炸弹,讲一个程序员的“顿悟时刻”。
我用三种语言,写了三遍同样的软件
过去20年,我为了处理PDF,可没少折腾。我试过:
1. Python:用个叫PLY的工具,像个刚学编程的小白,一步一步解析。
2. C++:用更高级的工具Flex和Bison,像个中学生,拿着计算器算语法。
3. C++(再战):自己手写“递归下降解析器”,像个学霸,非要手算微积分。
最后,我决定试试Rust——一个号称“内存安全、性能炸裂”的新语言。
我心想:不就是写个PDF处理工具嘛,照着C++的路子抄一遍,岂不美滋滋?
结果……Rust编译器直接给我一巴掌:“你这代码,不行!”
Rust:你这代码,我编译不了!
我照着C++的老套路,在Rust里搞了个“对象树”,每个对象都用指针连来连去,像蜘蛛网一样。
结果Rust编译器疯狂报错:
> ❌ “这个指针的生命周期是啥?”
> ❌ “你这里又改又读,想干啥?!”
> ❌ “你这内存管理,迟早出事!”
我整整折腾了一周,想尽办法“说服”Rust编译器放我一马。结果它油盐不进,死活不让我编译通过。
我崩溃了,仰天长叹:“Rust啊Rust,你是不是在针对我?”
最后,我认输了,决定换个思路:既然你Rust不让这么写,那我就按你的规矩来!
灵光一闪:用“枚举”代替“指针链”
我放弃了C++那种“万物皆对象、指针乱飞”的老思路,改用Rust的枚举(enum) 来表示PDF里的各种数据。
你可能不知道“枚举”是啥,我打个比方:
- C++的做法:
把“名字”“生日”“爸爸”“妈妈”都做成独立的小纸条,然后用回形针(指针)连起来。
想删一个人?好,你得一张张撕纸条,一个个拆回形针,累死你。
- Rust的新思路:
直接拿一个大信封,把所有信息全塞进去。
想删?直接把信封扔垃圾桶,完事!
而且,Rust还教我一个小技巧:短字符串直接写在信封上,不用贴纸条!
比如“name”“birthday”这种短词,根本不用申请内存,省时省力!
结果:性能直接起飞!
我一测性能,好家伙——Rust版本比C++快了整整3倍!
不是因为Rust语言本身多牛,而是Rust逼我用了更聪明的内存结构。
你猜怎么着?如果我当年用C++也这么写,C++可能还更快!但问题是——我根本没想到还能这么写啊!
来算笔账:删一个对象,要多少操作?
假设我们要删掉这个“Michael Doe”的信息:
json
{
"name": "Michael Doe",
"birthday": [1995, 3, 10],
"father": R-0,
"mother": R-1
}
- C++ 老方法:
- 释放8个对象(数字、链接、数组、字符串……)
- 减13次引用计数(每次减都要判断要不要删)
- 总共15次释放 + 13次判断,像在玩扫雷,步步惊心。
- Rust 新方法:
- 释放1个数组、1个哈希表、1个长字符串
- 其他短字符串根本没分配内存!
- 总共3次释放,0次判断,干净利落,像一键清空回收站!
所以,Rust真的比C++快吗?
不一定。
但如果让你用“最自然、最顺手”的方式写代码,Rust会自动把你往高性能的路子上推。
而C++呢?它像一辆跑车,性能猛,但你要是开得不好,分分钟撞墙。
Rust呢?它像一辆智能电动车,方向盘会自动纠正你的错误,还顺便带你抄近道。
最后,作者的灵魂发问:
1. C++程序员们,你们现在还用2005年的老套路吗?
当年没有std::variant,没有“小字符串优化”,现在有了,你们改了吗?
2. 你最喜欢的编程语言,有Rust这种“枚举大法”吗?
能不能也写出这么快、这么安全的代码?
总结金句:
> Rust不是更快,而是它不让你写慢代码。
> 它像一个严格的数学老师,不让你跳步骤,结果你一算,嘿,反而算得更快了!
所以,有时候——不是你不够聪明,而是你用的工具,没逼你变聪明。
(完)
P.S. 如果你现在还在用C++写指针满天飞的代码,小心Rust哪天找你“谈心”哦~