我不是编译器专家

工作多年以来,我深刻的体会到一个规律,那就是做过编译器工作的人,似乎很容易产生高人一等的心理,以至于在与人合作中出现各种问题。由于他们往往也存在偏执心理和理想主义,所以在恶化人际关系的同时,也可能设计出非常不合理的软件构架,浪费大量的人力物力。

我曾经提到的 DSL 例子,就是这样的两个人。他们都自称做过编译器,所以成天在我面前高谈阔论,甚至在最基础的概念上班门弄斧,显示出一副“教育”其他人的姿态。其实他们只有一个人做过 parser,还不算是真正的编译器工作,却总显示出高深莫测的模样。像哲人一样捋捋胡子,摇摇脑袋,慢条斯理,嗯…… 另外一个完全就是外行,只是知道一些术语,成天挂在嘴边。每次他一开口,我都发现这个人并不知道他自己在说什么,却仍然洋洋得意的样子。

我是被他们作为专家请来这个公司的,来了之后却发现他们唯一想做的事情,是在我面前显示他们才是“专家”。他们也问过我问题,可是我发现他们并不想知道答案,因为我说话的时候他们并没有在听。不管说什么问什么,他们似乎只想别人觉得他们是最聪明的人。“Yin,你知道 X 吗?” 当然他期望的是你说不知道,这样他就能像大师一样,把这个刚学到的术语给你讲半天。

每当这个时候,我就想起一个前同事喜欢说的一句话:“你问我,是因为你不知道,还是因为你知道?”

更糟的事情是,这其中一人还是 Haskell 语言的忠实粉丝,他总是有这样的雄心壮志,要用“纯函数式编程”改写全公司的代码……

遇到这样的人是非常闹心的,到了什么程度?他们经常雄心勃勃用一种新的语言(Scala,Go……)试图改写全公司的代码,一个月之后开始唾骂这语言,两个月之后他们的项目不了了之,代码也不知道哪里去了。然后换一种语言,如此反复…… 因为烦于他们在我面前高谈阔论,我干脆换了一个部门,不再做跟语言和编译器相关的事情。

有些美国公司在招人的时候表示,对简历里提到“做过编译器”的求职者有戒备心理,甚至直接说“我们不招编译器专业的人”。以至于我也曾经被过滤掉,因为我在 Coverity 做过编译器相关工作。编译器专业的人本来可以做普通的程序员工作,为什么有公司如此明确不要他们呢?我现在明白为什么了,因为编译器专业人士有大概率是性格很差的团队合作者,喜欢显示出高高在上,拯救世界的姿态,无法平等而尊重的对待其他人。

在 Coverity 和之后的其它公司遇到的编译器人,也或多或少存在差不多的问题。他们下意识里把自己看成是最高档次的程序员,所以对其他人总是高高在上的气势。

很多人也把我叫做“编译器专家”。我一直没有正式拒绝这个称呼,每每遇到真正的编译器专家,我总觉得自己不是那个圈子的。不是我不能做编译器的工作,而是他们的认识水平,理念和态度和我格格不入。

所以我应该明确表个态:我看不起编译器这个领域,而且我本来就不属于这个领域。就最后学习的专业,我是一个编程语言(PL)研究者,从更广泛的角度来看,我是一个计算机科学家。有人听了“科学家”一词总是误以为我在抬高自己,而在我心目中“科学家”仅仅是一个职业,就像“厨师”一样,并不说明一个人的水平。科学家有好的,也有很差,素质很低的。

业内人士经常混淆编程语言(PL)和编译器两个领域,而其实 PL 和编译器是很不一样的。真懂 PL 的人去做编译器也会比较顺手,而编译器专业的却不一定懂 PL。为什么呢?因为做编译器一般是专注于“实现”别人已经设计好的语言,比如 C,C++。他们必须按照语言设计者写好的语言规范(specification)来写编译器,所以在语言方面并没有发挥的空间,没有机会去理解语言设计的微妙之处。

很多编译器工程师并没有接受过系统的 PL 理论教育,有些甚至是半路出家,在学校里根本没碰过编译器,也没研究过 PL。比如我的第一个公司 Coverity,招进去的很多人从来没碰过编译器,也不懂 PL。Coverity 的领导天真的向他们宣布:“我们能教会你们一切!” 然而很可惜,PL 的功夫根本不是一个公司在短期能够传授的。Coverity 没有这个能力,Google,Facebook,Intel,微软…… 都没有这个能力。

由于缺乏对 PL 理论的深入研究,编译器人往往用井底之蛙的眼光来看待语言,总以为他们实现过的语言(比如 C++)就是一切。一个语言为什么那样设计?不知道。它还可以如何改进?不知道。“它就是那个样子!” 这是我常听编译器人说的话。

许多编译器人把 C++ 的创造者 Stroustrup 奉为神圣,却不知道 Stroustrup 在 PL 领域算是实力比较弱的。Stroustrup 曾经在 2011 年 11 月 11 日来到 IU 进行关于 C++11 的演讲,IU 的资深 PL 教授们都有到场。Stroustrup 谦卑的说:“我需要向你们学习很多东西来改进 C++。” 他说的是实话,因为 IU 的教授们在语言设计上确实比他强很多。

编译器人所崇拜的大师,在 PL 研究者眼里其实不算什么。编译器人与 PL 研究者在这类见识上的差距,足以说明编译器人并不真懂 PL。

实际上做编译器是很无聊的工作,大部分时候只是把别人设计的语言,翻译成另外的人设计的硬件指令。所以编译器领域处于编程语言(PL)和计算机体系构架(computer architecture)两个领域的夹缝中,上面的语言不能改,下面的指令也不能改,并没有很大的创造空间。

编译器领域几十年来翻来覆去都是那几个编程模式和技巧,玩来玩去也真够无聊的。起初觉得新鲜,熟悉了之后也就那个样了。很多程序员都懂得避免“低水平重复”,可是由于没有系统的学习过编译器,他们往往误以为做编译器是更高级,更有趣的工作,而其实编译器领域是更加容易出现低水平重复的地方,因为它的创造空间非常有限。

同样的编译优化技巧,在 A 公司拿来做 A 语言的编译器,到了 B 公司拿来做 B 语言的编译器…… 大同小异,如此反复。运气好点,你可能遇到 C,C++,Java。运气不好,你可能遇到 JavaScript,PHP,Go 之类的怪胎,甚至某种垃圾 DSL。但公司有要求,无论语言设计如何垃圾,硬件指令设计如何繁琐,你编译出来的指令必须能正确运行所有这语言写出来的代码。你说这活是不是很苦逼?

虽然苦逼,编译器人往往自高自大,高估自己在整个 IT 领域里的地位,看低其它程序员。编译器人很多认为自己懂了编程语言的一切,而其实他们只是一知半解。从我之前怼 Chris Lattner 的一些文章(链接1链接2)你也许可以看出来,虽然是编译器领域声名显赫的人物,却在设计 Swift 语言的早期犯下我一眼就看出来的低级错误,改了一次居然还没对。随便找个 PL 专家商量一下,也不至于犯这样的错误。这就是所谓“骄傲使人落后”吧。

编译器领域最重要的教材,龙书和虎书,在我看来也有很多一知半解,作者自己都稀里糊涂的内容。而且花了大量篇幅讲 parser 这种看似高深,实则肤浅的话题,浪费读者太多时间,误导他们认为 parser 是至关重要的技术。以至于很多人上完编译器课程,只学会了写 parser,对真正关键的部分没能理解。龙书很难啃,为什么呢,因为作者自己都不怎么懂。虎书号称改进了龙书,结果还是很难啃,感觉只是换了一个封面而已。

我曾经跟虎书作者 Andrew Appel 的一个门徒合作过,当时这人是 IU 的助理教授。借着一次我跟她做 independent study 的机会,逼我写扯淡而毫无意义的论文,而且对人非常的 push 和虚伪。作为普林斯顿大学毕业的 PhD,学识水平跟 IU 的其他教授格格不入,却在待人接物方面显示出各种“贱”,对编译器领域的“牛人”各种跪舔,随时都在显示自己以前在某某人身边工作过,那神情好像在说“你们见识过吗?” 那是我在 IU 度过的最难受的一个学期,这使我对“编译器人”的偏见又加深一层。

编译器领域的顶级人物如此,其它声称做过编译器的人也可想而知了。大部分自称做过编译器的人,恐怕连最基本的的编译器都没法从头写出来。利用 LLVM 已有的框架做点小打小闹的优化,就号称自己做过编译器了。许多编译器人士死啃书本,肤浅的记忆各种术语(比如 SSA),死记硬背具体实现细节,无法灵活变通。

所以我常说,编译器是计算机界死知识最多,教条主义最严重的领域之一。经常是某人想出一个做法,起个名字,其他人就照做,死记硬背,而且把这名字叫得特别响亮。你要是一时想不起这名字是什么意思,立马被认为是法国人不知道拿破仑,中国人不知道毛泽东。你不是做编译器的!

这就是为什么虽然有多次编译器的工作机会,包括 Apple 的 LLVM 部门,我最后都没去。进入 Intel 的时候,本来编译器部门也是一个选择,可是再三考虑之后还是选择了其它方向。因为我很清楚的记得,每一次做编译器相关工作都是非常压抑的,需要面对一些沉闷古板而自以为是的人,而且内容真的是重复,无聊和枯燥。

我唯一敬佩的编译器作者是 Kent Dybvig,但我也不想跟他一起做编译器。最近很多 AI 芯片公司的“AI 编译器”部门找我,我全都拒绝了。我不喜欢身边围绕着这些人,做着这些事。我宁愿去卖烧饼也不想做编译器。

所以对于曾经做过编译器的人,在面试的时候一定要深刻了解他们的性格,态度和做事方式,看他们是否能看淡这些,能否平等对待其他人。否则自视很高的“编译器人”进了公司,很可能对团队成为一种灾难。

我写这篇文章是为了警醒广大 IT 公司,也是为了在精神上支持其它程序员。我希望他们不要被编译器的“难度”迷惑了,不要被自称写过编译器的程序员吓唬和打压。你们做的并不是更低级,更无聊的工作。正好相反,真正可以发挥创造力的空间并不在底层的编译器一类的东西,而在更接近应用和现实的地方。

每当有人向我表示编译器高深莫测,向往却又高攀不上,我都会给他打一个比方:做编译器就像做菜刀。你可以做出非常好的菜刀,然而你终究只是一个铁匠。铁匠不知道如何用这菜刀做出五花八门,让人心旷神怡,米其林级别的菜肴,因为那是大厨的工作。要做菜还是要打铁,那是你自己的选择,并没有贵贱之分。