我给Geth提了个PR,然后被教育了
不是每个程序员都敢碰以太坊的代码,尤其是Geth,这个运行了十年的“老古董”,每行代码都像祖宗传下来的瓷器,碰坏了赔不起,但我这人有个毛病,越是觉得不能碰的东西,越想知道它到底哪儿疼。

三个月前,我在跑一个私有链节点时,发现一个诡异的现象:同步到某个区块高度后,内存占用会突然飙升200MB,随后又缓缓回落,这个周期性的“呼吸”让我浑身难受,我翻了半天日志,锁定在state trie的缓存清理逻辑上,直觉告诉我,这里有个重复计算被垃圾回收器反复触发,但Geth的代码库里,这种优化坑深不见底,我犹豫了三天,最后还是fork了仓库,写了一个看起来“自以为聪明”的补丁。
那个补丁的核心很简单:把原来每次区块处理都重建的临时trie节点缓存,改成只失效部分陈旧条目,我当时的想法是,用空间换时间,减少重复的hash计算,写完后,我跑了自己的测试网,数据确实好看,内存峰值降了18%,同步速度还快了3%,我挺得意,码了一篇长篇PR描述,语气里带着“我知道你们没想到”的傲慢。
提交后的第一个周末,我就被现实抽了一耳光,Geth的核心维护者之一,那位在伦敦的先生,回复了我,他没夸我,第一句话是:“你测的是单条链,但我们的节点同时跑着快照同步和状态修复,你的补丁会让那个路径的缓存永久失效。”后面跟着一个链接,指到一段我压根没看过的代码分支,我当时脸烧得慌,他继续说:“优化不是让一匹马跑得更快,是让整个马群不打架。”
我灰溜溜地撤回了PR,但没放弃,我开始重读那部分代码的git历史,看谁在什么commit里改过什么,为什么改,我读了那些看似废话的注释,发现每条背后都对应着某个特定的失败案例,比如有一句“此处不能加锁,因为会把读放大”,底下是一个三年前的事件链接,我开始明白,在这个项目里,任何“优化”都必须回答一个问题:你破坏了什么已有的假设?
第二版补丁,我完全换了思路,我不去改缓存逻辑了,而是分析当前代码里,那个最耗时的循环里,有两次完全相同的哈希查询,只是间隔了三行代码,这可能是历史遗留的冗余,我做了个小工具,专门统计这种重复计算热点,结果找到一共七处,我给每处都写了单元测试,并对比了gas消耗和CPU采样数据,这次,我的PR描述只有三句话,附上数据图表。
等待回复的那周,我反而平静了,不是不在乎,而是我想通了:开源贡献的本质,不是证明你的代码比别人的好,而是证明你理解了别人的痛苦,Geth的维护者们,每天要面对上百个issue,很多是“我节点崩了”却毫无堆栈的抱怨,他们最怕的就是有人随手甩来一个“优化”,却没想过这个优化会怎么在极端的网络延迟下表现,在畸形的交易池里表现,在硬盘即将写满时表现。
那次PR被合并了,但只是其中三处冗余查询的清理,负责人给我的反馈是:“这个方向对,但你的第一版里以为我们不知道的缓存问题,其实我们在两年前用另一种方式解决了,你可以看下state.snapshot下的那个文件。”我打开那个文件,发现他们确实用了一个我完全没见过的“分代隔离”设计,那一刻我才承认,所谓的“代码优化”,很多时候是在和已经存在的解决方案赛跑,而不是和代码本身较劲。
我依然会看Geth的库,但我不再急着提交,我开始给那些新人的PR写代码评审,用他们当初“教育”我的方式,我会问:“你考虑过归档节点模式吗?你测试过在无状态客户端下这个改动吗?”有次一个日本人抱怨我回复太慢,但他的补丁确实有一行会panic,我复制了那段代码,跑了一个fuzz测试,把结果贴给他,他立刻改了,还发推特感谢我。
回看这整个过程,我发现最讽刺的是:我最初以为开源贡献就是“我来修东西”,最后才明白它是“我学习别人的修法,并让它更顺手”,Geth的代码仓库里,藏着十年间无数次的争吵、妥协、灵光一现和深夜的教训,每一次提交,都是在你自己的名字旁边,又多了一个需要负责的角落。
如果你也想做类似的事,我唯一能给的劝告是:先去读那十年前的首次提交,看开发者怎么把一个简单的状态树搞成现在的模样。 然后挑一个你真正跑崩过、让你骂过娘的bug去追,别一开始就想“优化”整个系统,你连那个系统的“坏习惯”都还没摸清呢。
我最后的那个补丁,改动只有十一行,去掉了一个冗余的数组边界检查,它节省的gas微乎其微,可能只相当于每千笔交易省出一杯温水,但合并那天,我还是点了那个绿色的按钮,并且截图发了个朋友圈,配文是:“这十一行,够我吹一年。”底下有同行留言:“吹什么,你这行代码我们早就在别的链上跑过了。”我笑着没回,因为我知道,他说的对,但那是他跑过的,我跑的,是在这三年里,断断续续喂进去的我自己的时间,和一次次脸红心跳的教训。
写完这篇文章的时候,我又去看了眼那个PR的讨论区,最后一条评论是那位伦敦维护者发的,只有四个字母:“Thanks.” 然后关掉了,这四个字,比任何“厉害了”都重,因为你知道,他在感谢你,终于没把那些瓷器碰坏,反而擦亮了其中一块。






