在美帝面试工程师,是一种有趣的体验。以前曾经在朋友圈里发过一些体验,这两天,面试了两个很有意思的工程师,其中一个勾起了我一份尘封的回忆。今天我们讲讲这三个人。
(一)
SH 君。我昨天面试的 SH 君。他的背景是广告系统 —— 他在之前的公司现学现用,用 erlang 实现了 RTB system。他学习能力很强,系统知识丰富,考虑问题周全,仅仅使用了一年多 erlang,在其之上的造诣就相当不错。我和他聊了进一个小时,越聊越投机 —— 一般到这个时候我会问 candidate 一些奇奇怪怪的问题,比如,你最近在读什么书?最近发现了什么有意思的开源项目等等。对他,我抛出了这么个问题:如果 erlang core team 愿意在语言和 VM 层面为你实现几个 feature,你希望是什么?
这个问题非常 open,既考察 candidate 对已有系统的理解,又考验 candidate 知识的丰富程度。
出人意料地,他一口气提了三个愿望:1) 更好的 refc 管理,提高内存效率同时又不引发 “leak” 2) 引入 type system,最好像 haskell 那样严格区分 pure / impure function 3) 把 OTP 的核心功能,比如 application / supervision tree 做到语言级别,而非以 lib 形式提供。
对于 1) 和 2) 我不太意外。3) 很有意思,也很有想法。我让他进一步澄清 —— 他说,他虽然没有太多 akka 的 knowledge,但 akka 显然在某些方面青出于蓝而胜于蓝。akka 下,任意一个 actor spawn 出来,都有默认的 supervisor,erlang OTP 提供了 supervision tree,可语言或者 VM 本身却没有把这个作为缺省行为 —— 如果我们因为上下文的需要临时 spawn 一个 process,绝大多数情况,会额外去 monitor 它以便妥善进行 error handling,既然如此,为何不默认就 supervise 呢?
甭管这个想法对与不对,单是这份思考,就超过很多很多的程序员了。
(二)
B 君。今天面试的是 B 君。android 工程师。粗一看简历,B 君就让我回想起了很久前面试的 S 君(下文会说),原因很简单:又一枚硅谷活化石。B 君 80 年开始工作时,我还没出生。那是是 DEC 如日中天的年代(谁都不曾料到把 IBM 逼到墙角的小型机之王,几年后就就被 PC 的浪潮冲击得七零八落),他在 DEC 工作,随后换了不下十家公司,著名的有 amazon 和 twitter。如果按照正常孩子十七岁的花季上大学推算的话,他现在已经年逾古稀。在国内程序员圈子还在热火朝天地讨论程序员 35 岁后该干嘛时,他却精神矍铄地参与一线 android 开发。并且,他是三本 android 书籍的作者,最近一本于 16 年出版,叫 android concurrency。虽然老爷子不幸错过了计算机近代史上几乎所有能发家致富的机会,他依然乐乐呵呵,没有自艾自怜。
和他面试的前一个小时,我上 amazon 翻看这本书的评论和可供预览的章节。平心而论,书写得并不算是优秀,概念解释得不够清晰(面试时也印证了他对 concurrency 和 parallelism 没有清楚的定义,可能我是一个对 concept 过于较真的人吧),对 android 之外 concurrency 的 big picture 也不了解(比如 actor model,CSP,STM 等)。当然,能写书,已经非一般人所及,他的 android 的造诣不浅,而且在近六十岁高龄活跃在技术一线还不断写书,实在是我辈之楷模。(和老爷子闲聊时,他说他还会继续出书)
(三)
S 君。和 S 君的面试已经过去一年多,如若不是当初写了篇未完成的文章,保留了些许鲜活的记忆,我对 S 君的记忆仅仅停留在「他是个活化石」的阶段。
这是当时的文章:
10多年前我刚加入 Juniper 时,同事们每天中午都要一起聚餐。有一阵子,来了很多总部的华人工程师,聊起硅谷的各种轶事,一位做 Kernel 的大神同事 Yi 说起他有次在钓鱼,和旁边的老头闲扯,一扯扯出来个以太网的发明者。那时我就感慨,硅谷 TM 真是个神奇的地方。
后来又陆陆续续听到同事们不少关于偶遇硅谷活化石的故事,比如面试遇到和盖茨乔布斯同时代的程序员等等,听得我如痴如醉。
上周终于遇到一个和乔老爷子同时代的面试者 S君,78年印第安纳大学毕业。MIPS 的早期员工,NeXT 早期员工(他是在乔老爷子被自己亲儿子苹果扫地出门,刚领养了 NeXT 这个义子后加入的),数个公司的 VP,包括 NEC(好吧,NEC现在已近算不得什么好公司了,不过曾经火过)。
然后他来我们 Tubi TV 这座小庙面试!
这在国内是无法想象的!你能想象鲍岳桥简晶这些让人敬仰的超级程序员前辈们跑到你的 startup 来面一个程序员的职位么?
S君住在 Atherton,硅谷著名的富人区,想来是不缺钱的。整个面试过程中,有个问题好几次我几乎脱口而出:您看上去并不缺一份薪水,凭资历(或者人脉)也可以去一些大公司领个闲置安度晚年好了,为何要来 Tubi TV 这样一个处在需要事事操心的阶段的创业公司?但顾忌到文化的差异,我强忍住了。
作为热身,我问了他在 NeXT 的履历,他说自己做 object-c compiler。我对 compiler 并非谙熟,不敢造次,扯了几句后就把话题移到乔老爷子身上。S君立刻打开了话匣子,讲起了各种轶事(程序君按:妈蛋我当时为啥没把这些轶事记录下来),随后他目光一暗,说老爷子自从接手 Pixar 后,精力就都投在那边了,在 NeXT 就很少出现他的身影。
随后我们聊起了 MIPS。我渐渐感受到他对技术的那份热爱 —— 这也可以解释他辗转多家公司,有大大小小公司的 VP title,却还愿意在一线做事。
他说他在加入 NeXT 之前两年,1984年(好吧,那时候我还穿着开裆裤满地连滚带爬地蹒跚学步呢),加入刚刚创立的 MIPS,亲历了一套指令集从学术界到工业界的转型,因此对 MIPS 饱含感情。因为在 Juniper 做过中断处理相关的代码,我对各种 RISC CPU,尤其是 MIPS 和 ARM 比较熟悉,于是便班门弄斧,用 branch delay 试了试他的底。他说他主要的工作是优化 TLB,设法优化掉 CAM(那时估计还没有TCAM)和 DRAM 之间的 SRAM(那个年代 SRAM 无比贵),但指令流水线也是懂的。在他如同教科书般详细介绍完 branch delay 在早期几代 MIPS CPU 的演进后,我突然想起一个困扰我多年的问题:为何 MIPS 有 branch delay,而同为 RISC CPU 的 ARM / PowerPC 却没有在指令级别做这种事情。他解释说就 RISC 而言,MIPS 是更纯粹的 RISC CPU,而 ARM / PowerPC 在工业界已经为了性能做了些改进(妥协),另外,暴露过多的流水线的逻辑给软件工程师(注:主要是写编译器和 Kernel 底层代码的工程师)会使得编译器过于复杂(静态的编译难以完美预测指令动态执行时的状态)。所以他觉得 ARM 的做法是正确的,尤其是后来 hyperthread(超线程)的出现印证了这一点,pipeline 的复杂已经使这种简单的优化失去了意义,唯有 CPU 自己的乱序执行才是王道。
我听得津津有味,这个思路不就是 imperial programming(程序员告诉 CPU 做事的步骤)和 functional programming(程序员告诉 CPU 想干什么)的差别么?
既然提到了 ARM,我便顺势问他是否了解 literal pool。
可惜,文章在这里就戛然而止,后来的面试过程我已经记不清楚,唯一能确定的一点是,他没有来 Tubi TV。
(四)
本来有感而发,火车上随便写写,发篇长文字图片了事,不经意间写了这么些。程序员的人生道路很长,未来还有一波又一波的浪潮,大部分人注定会错过所有扬名立万的机会,一辈子做一个普通的勤勤恳恳的程序员。对于这几个面试,我其实有蛮多感悟的,但思虑再三,还是决定就此搁笔,让大伙儿自己思考吧。