工程哲學:John Carmack,把效能當成一種道德工藝

重點摘要
- Carmack 把效能當成一道道德課題,而非一輪事後的最佳化。程式碼與硬體物理極限之間的落差就是浪費,而浪費是您自己做出的選擇。
- 他的方法是做減法:把問題理解到根基,剝除到只剩快速而簡潔的核心,並拒絕每一項會拖慢這個核心的功能。
- 當底層問題本身改變了,他便從零重寫。Quake 捨棄了讓 id 一舉成名的引擎,因為真正的 3D 與偽裝的 3D 根本是兩個不同的問題。
- 他在公開之中工作——先是每日的
.plan日誌,後來把引擎開源——憑藉一個信念:會被公開的程式碼,是您寫得更誠實的程式碼。
核心原則
「光速爛透了。」——John Carmack1
這是一句玩笑話,卻也是整套哲學。Carmack 是針對網路延遲——封包橫越一整片大陸所需時間的那道硬性物理下限——說出這句話的,但這份心境貫穿了他寫過的每一行程式。機器受物理支配,而工程師的職責,是在問題允許的範圍內,盡可能逼近物理極限。不是「夠近就好」,而是物理所容許的最近。使用者與光速之間的一切都是浪費,而浪費是您做出的選擇。
Carmack 把效能視為一道道德課題,而非一輪事後的最佳化。多數軟體累積遲緩的方式,就像房子堆積雜物——一次一個看似合理的決定,每個都說得過去,加總起來卻無法辯護。Carmack 的紀律是拒絕這種累積:把問題理解到根基,剝除到只剩快速而簡潔的核心,然後交付出去。同樣的信念,也支撐著另一個論點:效能不是您加上去的功能,而是您沒能守住的性質——您無法把一個慢系統最佳化成快系統;您是先打造一個快系統,然後守住它。
而且他把過程攤開來看。十多年間,Carmack 把自己每日的工程日誌——他的 .plan 檔——公開到開放的網際網路上,任何人用 finger 客戶端都能讀。21990 年代最棘手的 3D 渲染難題,幾乎是即時、公開地被解開。在公開之中工作並非行銷,那與程式碼本身出於同一種本能:沒有隱藏狀態,沒有任何您無法檢視的東西。
背景脈絡
John D. Carmack 於 1970 年 8 月 21 日出生於堪薩斯州的 Shawnee Mission。3 他在密蘇里大學堪薩斯城分校念了兩個學期,便離校以寫軟體為生。沒有正式的師徒訓練,也沒有學位。他學習圖形程式設計的方式,與 demoscene 如出一轍——讀硬體手冊、量測晶片實際的行為,並不斷寫組合語言,直到數字對上為止。
他落腳於 Softdisk,一家位於路易斯安那州 Shreveport 的軟體暨磁碟雜誌公司,負責一份名為 Gamer’s Edge 的遊戲訂閱刊物。在那裡他結識了 John Romero、Tom Hall 與 Adrian Carmack(與他無親屬關係)。1990 年 9 月,Carmack 做出了一個在 PC 上本不該成立的展示:在 EGA 硬體上跑出流暢、媲美主機的橫向捲動。1990 年的 IBM PC 每一幀都要重繪整個畫面——對捲動遊戲而言太慢了。Carmack 的技術自適應圖塊更新(adaptive tile refresh),利用了 EGA 硬體鮮為人知的特性,把已繪製好的畫面整體滑移,只重繪新露出來的邊緣。4 團隊把任天堂《超級瑪利歐兄弟 3》的第一關重製成一個 PC 展示來證明這件事。任天堂婉拒了,團隊則留下了這套引擎。
1991 年 2 月,他們離開 Softdisk,創立 id Software。這套模式早已定型:找到沒人解開的問題,在硬體層級把它解開,再在解法之上打造產品。Carmack 後來在材質貼圖 3D 上又做了一次,接著是真正的多邊形 3D,再來是虛擬實境。圍繞著他的氛圍——Michael Abrash 的《Graphics Programming Black Book》、demoscene 那種逐週期計算的文化——把處理器當成必須被精確理解、而非被約略估計的對象。Carmack 讓這種文化聲名遠播。

作品歷程
Commander Keen 與 Doom:快速的核心(1990–1993)

Commander Keen in Invasion of the Vorticons(1990 年 12 月)是第一款建立在自適應圖塊更新之上的商業遊戲。它的意義,與其說在於它是一款遊戲,不如說在於它是一個證明:對硬體的細緻解讀,能夠彌平通用 PC 與專用主機之間的落差。流暢的捲動不是疊加在表面的圖形把戲,它本身就是引擎。
Doom(1993)是 Carmack 方法的典範範例。為了在 1993 年的 PC 上夠快地渲染場景,他採用了二元空間分割(binary space partitioning)——BSP 樹,源自 Carmack 翻找出來並加以改造的一篇 1980 年學術論文——預先計算牆面必須被繪製的順序,讓引擎絕不重複繪製一個稍後會被覆蓋的像素。5 Doom 並非真正的 3D;它是一張 2D 地圖,靠著足夠巧妙的手法渲染得彷彿具有體積感。這個區別正是重點。Carmack 沒有打造最通用的系統,他打造的是在當時實際存在的硬體上跑得快的系統,並拒絕每一項會拖慢核心迴圈的功能。快速、簡潔的核心,交付出去。
Quake:以軟體實現真正的 3D(1996)

Quake(1996)是從零的重建。Doom 偽裝深度,Quake 則在消費級 3D 加速卡尚未普及之前,以軟體渲染出貨真價實的三維多邊形世界——傾斜的表面、可以上下仰望、真實的幾何。6 這套引擎結合了預先計算的 BSP 可見性、離線光照圖(lightmaps)與手工調校的組合語言,做到了當時的常識認為那個年代的 CPU 辦不到的事。id 後來釋出了 GLQuake,一個 OpenGL 渲染器,協助讓消費級 3D 顯示卡站穩腳跟。
Quake 是 Carmack 整套立場一次盡顯的作品:他捨棄了讓公司成名的引擎,把新問題(真正的 3D)理解到根基,然後重建。沒有為了重用而重用。先前的解法並不神聖;神聖的是問題。
開放的 id 引擎與 .plan 檔(1997–2011)
對於讓他致富的程式碼,Carmack 做了兩件不尋常的事。他公開了自己每日的工作日誌——.plan 檔——讓工程在發生的當下就清晰可讀。2 接著,他把引擎送了出去。id 在 1997 年將 Doom 引擎開源、1999 年開源 Quake,並隨著下一代 id Tech 出貨,持續釋出每一代的原始碼,一路延續到 Doom 3 及其後。7 他的理由很直白:釋出舊程式碼能讓更年輕的開發者學到這東西實際上是怎麼造出來的,而「人們珍視的自由軟體,會為世界增添財富」。8
這份意願,是多數效能至上的工程師永遠到不了的境界。Carmack 的工藝,是把私下的紀律攤在公眾面前。願意被閱讀——讓任何人都能檢視每日日誌,乃至最終檢視原始碼——本身就是一筆關於品質的交易。會被公開的程式碼,是您寫得更誠實的程式碼。
Oculus VR:延遲的下限(2013–2019)

在 Oculus,Carmack 畢生的宿敵——延遲——成了問題的全部。他寫道:「使用者頭部的實體移動,與頭戴顯示器更新後送達其雙眼的光子之間的延遲,是提供高品質體驗最關鍵的因素之一」,而可被察覺的頭部追蹤延遲「也是模擬器暈眩的主因之一」。9 他訂下了一個預算——目標約莫是 20 毫秒的「動作到光子」(motion-to-photon)——並把管線的每一個階段都當成可以搶回幾微秒的地方。他的時間扭曲(timewarp)技術,會在顯示前的最後一刻,對一個已渲染好的幀做重投影,藉以吸收渲染過程中發生的頭部移動。9 這又是自適應圖塊更新,只是晚了二十三年:不要重繪您可以重用的東西,並對照物理極限來量測結果。
方法
這套方法,在三十年、四個問題領域之間始終如一。
把問題理解到根基。 Carmack 讀硬體手冊、量測實際行為,並從第一原理出發,而非依循慣例。BSP 樹、光照圖與時間扭曲都不在任何既有的劇本裡;它們是從問題實際所需推導出來的。
剝除到只剩快速、簡潔的核心。 Doom 不是 3D,因為在 1993 年的硬體上,要讓人感覺像 3D 並不需要真正的 3D。這份紀律是做減法:辨識出內層迴圈,把它弄快,並拒絕那些會拖慢它的功能。
當問題改變,就從零重寫。 Quake 並未延伸 Doom 引擎。一旦底層問題已經移動,Carmack 就把一個可運作的系統視為可拋棄之物。沉沒成本不構成理由。
深度、不受打斷的專注。 Carmack 的馬拉松式編碼從來不是為了耐力本身。把一整套引擎握在工作記憶裡——資料佈局、內層迴圈、各種邊界情況一次全在腦中——得花上數小時才能載入,而一旦切換情境便瞬間瓦解。他守護那個狀態的方式,就像他在渲染迴圈裡守護週期一樣:把它當成工作真正賴以運轉的稀缺資源。
後期:C 語言中的函數式風格。 到了 Doom 3 時期及其後,Carmack 開始偏好純函數,即便在 C 與 C++ 中也盡量減少可變狀態——不是趕時髦,而是因為沒有隱藏狀態的程式碼,其行為是可以預測的,這意味著更少的錯誤。10 這與 .plan 檔出於同一種本能:沒有任何您無法檢視的東西。
影響鏈
形塑他的人
Michael Abrash 是這條脈絡裡最接近「導師」的人。Abrash 關於 x86 圖形的著作——後來集結為《Graphics Programming Black Book》——把 Carmack 所實踐的那種逐週期計算、凡事必量的文化整理成體系。兩人後來在 id 共事,更晚又在 Oculus 共事,Abrash 在那裡成了首席科學家。(直接影響)
1980 年代末的 demoscene 與組合語言最佳化文化教會了那個根本的信念:處理器是可以被精確認識的,而程式碼與硬體天花板之間的落差,是您的責任。(奠基性影響)
John Romero,他在 id 的夥伴,扮演的是互補者而非老師。Romero 的設計與關卡作品,賦予了 Carmack 的引擎值得運行的東西。這段合作關係提醒著:一個快速的核心是必要的,卻非充分的——引擎之所以存在,是為了被玩。
他形塑的人
整個遊戲引擎產業。 BSP 可見性、光照圖,以及把成熟引擎開源的做法,都成了基本實踐。一整代的引擎程式設計師,是靠著閱讀 Carmack 選擇釋出的 id Tech 原始碼學會 3D 渲染的。
消費級 3D 圖形硬體。 Quake 的 OpenGL 路徑,是支持 3D 加速卡的早期商業論據,協助把 GPU 拉進主流 PC。
現代虛擬實境。 時間扭曲與那份毫不鬆懈的延遲預算,如今已是每一條 VR 管線裡的標準詞彙。Carmack 當年追逐的 20 毫秒目標,正是今日頭戴裝置不會讓人暈眩的原因。
貫穿的主線
Andrej Karpathy 從零重建神經網路,因為理解無法被轉移——您得自己推導出來。Carmack 用同樣的方式推導他的渲染器:不是從框架出發,而是從硬體與問題出發。而當 Linus Torvalds 推崇「好品味」——那種化解於通則之中的特例——Carmack 推崇的,則是在物理允許範圍內做最少工作的內層迴圈。兩者其實是同一個信念穿著不同的衣裳:正確的結構不是疊加在問題之上的裝飾;它就是問題本身,被正確地看見。(系列銜接)
我從中汲取的
我一直記著的這課是:效能即誠實。一個慢系統,通常是其作者從未把問題理解得夠透徹、找不到它快速核心的系統——他們堆疊抽象直到能跑,而「能跑」就是他們停下的地方。Carmack 則停在物理極限。這與品質是唯一的變數是同一套標準:問題從來不是「這夠快可以交付了嗎?」,而是「我究竟有沒有理解它為何這麼慢?」
在我如今所建造的世界裡——代理、工具迴圈、AI 系統——誘惑恰好與 Carmack 的紀律相反:堆疊框架、用更多模型呼叫去掩蓋延遲、從不去讀系統實際在做什麼。Carmack 的做法是剖析迴圈、找出佔主導的那一塊、把它理解到根基,然後把其餘的剝掉。那個信念——品味是一套可量測的技術系統,而非您空口主張的氛圍——正是從 1990 年一個 EGA 捲動把戲,一路貫穿到 2026 年一個代理框架的主線。
常見問答
John Carmack 的工程哲學是什麼?
Carmack 把效能視為一道道德課題,而非事後的補救。這份紀律是:把問題理解到根基,剝除到只剩快速而簡潔的核心,拒絕那些會拖慢核心的功能,並在底層問題改變時從零重寫。他還搭配了在公開之中工作——公布每日工程日誌、把成熟引擎開源——憑藉一個信念:您能檢視的程式碼,是寫得更誠實的程式碼。28
John Carmack 打造了哪些東西?
Carmack 於 1991 年共同創立 id Software,並擔任《Commander Keen》(1990,自適應圖塊更新)、《Wolfenstein 3D》(1992)、《Doom》(1993,基於 BSP 的渲染)與《Quake》(1996,真正的 3D 軟體渲染)的主程式設計師。他在二十年間陸續將 id Tech 各代引擎開源,擔任 Oculus VR 的技術長並主導「動作到光子」延遲的相關工作,後來又創立了 AI 公司 Keen Technologies。5679
什麼是自適應圖塊更新(adaptive tile refresh)?
這是 Carmack 於 1990 年構想出來的技術,用以在 IBM PC 的 EGA 硬體上實現流暢的橫向捲動——這套硬體原本因為每一幀都要重繪整個畫面而太慢。自適應圖塊更新利用 EGA 硬體特性滑移已繪製好的畫面,只重繪邊緣新露出來的圖塊,大幅削減了每一幀的工作量。它讓《Commander Keen》得以成真,也確立了 Carmack 的招牌手法:在硬體層級解決瓶頸。4
Carmack 為什麼要公布他的 .plan 檔並把引擎開源?
.plan 檔是一份每日工程日誌,最初可透過 finger 協定讀取,幾近即時地記錄著 id 的開發過程。2 Carmack 後來在每一代 id Tech 的後繼者出貨後便將其開源,主張釋出舊程式碼能幫助較新的開發者學會遊戲究竟是怎麼造出來的,而有價值的自由軟體「會為世界增添財富」。8 這兩種做法,都反映出與他的程式碼相同的原則:沒有隱藏狀態,沒有任何您無法檢視的東西。
資料來源
-
John D. Carmack, “The speed of light sucks.” Wikiquote,論網路延遲。廣泛引用自他 QuakeWorld 時期的網路工作;另見 Data Center Knowledge 的討論。 ↩
-
Robbie, “The Carmack Plan,” Garbage Collected,2017 年 10 月——論
.plan檔、finger協定,以及在公開之中工作。oliverbenns/john-carmack-plan 上封存的日誌橫跨 1996 年至 2000 年代,記錄了這項實踐長達數年的歷程。 ↩↩↩↩ -
“John Carmack.” DoomWiki。1970 年 8 月 21 日生於堪薩斯州 Shawnee Mission;密蘇里大學堪薩斯城分校;Softdisk;id Software 的創立。 ↩
-
David Kushner, Masters of Doom: How Two Guys Created an Empire and Transformed Pop Culture (Random House, 2003),第 3 章——將 Carmack 的流暢捲動突破,以及那場通宵重製《超級瑪利歐兄弟 3》的事,定在 1990 年 9 月於 Softdisk。Romero 的合作者 John Anderson 的 “The Saga of Dangerous Dave,” 亦予以佐證,文中把「Dangerous Dave in Copyright Infringement」定在 1990 年 9 月。技術細節:“Adaptive tile refresh,” Wikipedia,以及 Fabien Sanglard, “Commander Keen’s Adaptive Tile Refresh.” ↩↩
-
“Doom rendering engine,” DoomWiki——BSP 樹在 1993 年 5 月的 alpha 版與 10 月的 beta 版之間被採用;透過線段裁剪消除重複繪製。關於該技術的源頭:Sinclair Target, “How Much of a Genius-Level Move Was Using Binary Space Partitioning in Doom?,” Two-Bit History(2019)——將 BSP 樹追溯至 Henry Fuchs、Zvi Kedem 與 Bruce Naylor 於 1980 年的論文〈On Visible Surface Generation by A Priori Tree Structures〉(及其 1969 年美國空軍飛行模擬器的前身),並記述了 Carmack 為 Doom 對其所做的改造。 ↩↩
-
“Quake engine.” Wikipedia。以軟體實現的真正 3D 多邊形渲染(1996)、預先計算的可見性、光照圖,以 C 與組合語言寫成,後有 OpenGL 路徑。 ↩↩
-
“id Tech,” Wikipedia——記錄了各次原始碼釋出:Doom 引擎 1997 年(1999 年改採 GPL 授權)、Quake 引擎 1999 年、Quake II 2001 年、Quake III 2005 年,以及 Doom 3(id Tech 4)引擎於 2011 年——最後一次 GPL 釋出。概覽:“A graphical history of id Tech,” PC Gamer。 ↩↩
-
Brad Cook 對 John Carmack 的訪談,Apple.com(已封存),引用自 Wikiquote。「分享程式碼,似乎就是『該做的對的事』……人們珍視的自由軟體,會為世界增添財富。」另見:TechRadar, “id’s John Carmack sings praises of open source.” ↩↩↩
-
John Carmack, “Latency Mitigation Strategies”(已封存;原文發表於 2013 年 2 月)。原文:「使用者頭部的實體移動,與頭戴顯示器更新後送達其雙眼的光子之間的延遲,是提供高品質體驗最關鍵的因素之一」,以及「在對頭部移動的回應中察覺到延遲,也是模擬器暈眩的主因之一。」文中描述了時間扭曲重投影技術。VR 延遲目標的脈絡:PCGamesN, “John Carmack’s battle for 20 millisecond latency.” ↩↩↩
-
John Carmack, “In-Depth: Functional Programming in C++,” Gamasutra/Game Developer,2012 年 4 月 30 日:「軟體開發中很大一部分的瑕疵,源自程式設計師未能完全理解其程式碼可能執行於其中的所有可能狀態。以函數式風格寫程式,會讓呈現給您程式碼的狀態變得明確。」論偏好純函數、並盡量減少可變狀態以減少錯誤。 ↩