← 所有文章

Apple 的字型直譯器現已改用 Swift,速度還快了 13%

Apple 安全團隊發表了一項足以終結爭論的成果。TrueType hinting 直譯器是一個位元組碼直譯器,自 1991 年以來便在 Apple 平台上解析未受信任的字型資料,如今它已從 C 改寫為記憶體安全的 Swift,而且「平均而言,我們的 Swift 直譯器比它所取代的 C 直譯器快了 13%。」1 這篇文章由 Apple 安全團隊專注於 Swift 採用的成員 Scott Perry 撰寫,原始碼以參考實作的形式放在 GitHub 上,而正確性的標準並非「通過測試」,而是與 C 原版逐像素一致的渲染結果。1 記憶體安全、比 C 更快,並且自 2025 年秋季的版本起就已在生產環境中運作:這篇文章是迄今對「記憶體安全會犧牲效能」這項主張最有力的實證回答。

TL;DR

  • Apple 之所以將 TrueType hinting 直譯器從 C 改寫為 Swift,是因為字型解析器是攸關安全的攻擊面:該直譯器會執行內嵌於字型中的位元組碼,具備「由輸入驅動的控制流程、複雜的資料結構,以及謹慎的記憶體管理——正是那種難以做到完美、且記憶體錯誤更容易被利用的程式碼。」1
  • 這項成果已在 2025 年秋季版本中推出,「自啟用以來未曾收到任何錯誤回報」,且平均比 C 實作快了 13%。1
  • 效能提升來自具體且可移植的技術:以 ~Copyable~Escapable 數值型別消除參考計數與獨佔性檢查的開銷、以 Span 進行安全的序列存取、用投影型別包裝 C 結構以移除約佔執行時間 20% 的複製,以及讓泛型維持可特化。1
  • 驗證才是那份低調的傑作:一套在兩種實作上都達到 99.7% 涵蓋率的單元測試、一個由 fuzzer 從 1,000 萬份 PDF 精簡為 4,200 份文件、內嵌 25,572 種字型的語料庫、2,700 萬個字符各以四種變換渲染並逐點陣圖比對,以及將近是直譯器程式碼四倍的測試程式碼。1
  • 直譯器原始碼以 MIT 授權發布於 apple/truetype-hinting-interpreter-example,是作為參考實作的生產級程式碼。2

為什麼字型直譯器是一個安全議題

TrueType 字型可以包含程式。Apple 在 1980 年代末期創造的這套格式,內建了一個圍繞著專用位元組碼直譯器打造的 hinting 引擎,用以讓字型輪廓在低解析度顯示器上忠實地點陣化。1 當 TrueType 於 1994 年變得可內嵌於 PDF、並於 2008 年可內嵌於網頁時,這個直譯器便開始執行來自「網際網路任何地方的未受信任字型」中的程式。1 任何關注過 iOS 安全史的人都知道接下來的劇情:字型解析器曾承載過該平台上一些最著名的漏洞利用鏈,而這篇文章無需重述歷史便點出了結構性的原因。由輸入驅動的控制流程加上手動記憶體管理,正是記憶體錯誤滋生之處。

團隊面臨的限制讓這次改寫比從零開始的移植更為棘手。二進位相容性意味著既有的程式「必須繼續維持與先前相同的運作方式,實際上完全察覺不到背後已換上新的實作」,而由於 hinting 可能徹底改變字符在螢幕上的外觀,正確性被定義為「與 C 實作輸出完全相容」。1 是逐像素一致,而不是大致正確。

驗證方法論才是這個工藝故事的核心

在進行效能工作之前,團隊先建立起證明的機制。一套單元測試同時針對 C 與 Swift 實作,達到詳盡的涵蓋率——兩者皆 99.7%——並隨開源版本一同釋出。1 為了涵蓋真實世界的情況,他們使用 fuzzer 在不損失任何程式碼涵蓋率的前提下,將 1,000 萬份 PDF 檔案的語料庫精簡至 4,200 份;這些文件內嵌了 25,572 種字型,其 2,700 萬個字符各以四種變換渲染,並將產生的點陣圖與參考直譯器比對。1 到最後,團隊所撰寫的測試程式碼行數,將近是直譯器程式碼的四倍。1

這個比例正是值得內化的部分。之所以能放手大刀闊斧地改寫,是因為每一項最佳化都會對照一個能逐點陣圖回答「行為是否改變」的判準器。文章正是歸功於這個迴圈:詳盡的涵蓋率與定義明確的內部邊界「讓重構變得容易許多,進而加速了量測與修正的最佳化迴圈,同時將引入錯誤的風險降到最低。」1

這 13% 從何而來

文章將效能工作拆成四個類別,每一類都帶有一個可移植的啟示。1

用不可複製型別消除參考計數與獨佔性檢查。 Swift 的 ARC 與執行時獨佔性檢查會帶來開銷,而別名(aliasing)會使其惡化,偏偏直譯器的規格本身就內建了無法消除的別名數量。解法是架構層面的:全面採用 ~Copyable 數值型別,並將參考型別保留給高階抽象,再以 Span(於 Swift 6.2 引入,且可一路向後部署至 macOS 10.14.4 與 iOS 12.2)提供對序列的高效存取。1

停止在語言邊界進行複製。 C 程式碼將字符點儲存為一個包含八個陣列的結構,對快取友善卻不符合 Swift 的風格。最初的橋接程式碼會把這些資料複製進 Swift 再複製回來,而這些複製耗掉了新直譯器約 20% 的執行時間。1 取而代之的是包裝 C 結構的投影型別,在不複製的情況下仲介邊界安全的存取,遵循 WebKit 的 Safer Swift Guidelines:一個 @safe、不可複製、不可逃逸的結構,持有一個指向 C 元素的 Ref,且每個不安全的運算式都附上一則 // SAFETY: 註解,記載證成它的不變條件。1

省去短命的配置。filtermap 這類運算會進行配置,而只有當值逃逸時這項配置才重要。直譯器的堆疊彈出運算從一個會配置一個被彈出元素陣列的直觀版本,演化為一個延續傳遞(continuation-passing)的版本:呼叫端傳入一個閉包,在元素被移除之前對一個 borrowing Span 進行操作,並以編譯期獨佔性檢查保證該堆疊無法從閉包內部被變動。1 沒有堆積配置、沒有元素複製,而且其安全性論證是結構性的,而非靠約定俗成。

讓泛型維持可特化。 來自協定與泛型的動態派發通常可以被最佳化掉,但並非無條件如此。團隊對效能剖析的指引是:「若你在熱路徑上看到未特化的泛型或協定見證表,那就是個徵兆,代表最佳化器並未獲得足夠的可見性」,而該實作或許能受益於內聯(inlining)。1

最終的結果並未以可讀性換取速度。文章的論點是,Swift 的型別系統使得這些抽象——定點數值型別、一個內建轉換的堆疊元素、那些投影型別——一旦搭配最佳化建構,便「在大幅提升可讀性的同時帶來了零成本」。1 而團隊對範圍也坦誠以告:直譯器的內部狀態全是不可複製的結構,但最上層的型別仍是一個由 Objective-C++ 呼叫的 @objc 類別,因為「熱路徑很快,而冷路徑很方便。」1

那個低調的 agent 角度

接近結尾處有一段文字,值得比它的位置所暗示的更多關注。完成這次移植後,團隊「將我們學到的東西提煉為給 LLM 程式設計助理的指令,並從此在其他專案中成功運用」,LLM 提升了團隊將 C 與 C++ 轉換為 Swift 的效率。1 Apple 安全團隊正將移植專業知識編碼為 agent 指令,並在不同的程式碼庫之間重複使用——這正是 Apple 在本週期將其產品化為可匯出 agent 技能的同一種模式,詳見 Xcode 27 的 agent 技能匯出。一次手工打造的移植成了一份操作手冊;而這份手冊成了接下來十次移植的槓桿。

從中該汲取什麼

這篇文章確立了三項過去尚有爭議的主張。記憶體安全的 Swift 能在最熱的熱路徑——一個位元組碼直譯器——中取代攸關安全的 C。這項取代還能更快,靠的不是魔法,而是不可複製型別、複製消除,以及對特化友善的設計。而這次移植能被驗證到逐像素等價,前提是投入足夠的測試,團隊估算其規模約為實作的 4 倍。對於任何手上握有觸及未受信任輸入的 C 或 C++ 解析程式碼的人來說,這篇文章、那個開放儲存庫,再加上 Swift 6.4 的細粒度嚴格記憶體安全選擇性啟用,三者的組合讓「我們總有一天會移植」比上週明顯更站不住腳了。

常見問題

Apple 究竟改寫了什麼?

是 TrueType hinting 直譯器:那個執行字型內嵌 hinting 程式、讓字符輪廓能良好點陣化的位元組碼直譯器,自 1991 年的 System 7 起便是字型堆疊的一部分。1 它在 2025 年秋季版本中從 C 轉為記憶體安全的 Swift,渲染輸出與 C 實作逐像素一致。1

Swift 在這裡真的比 C 快嗎?

平均而言,是的:比它所取代的 C 直譯器快了 13%,這是以 macOS 上所有採用 hinting 的字型加上一組非系統字型樣本、按每字符 CPU 百萬週期數量測得出的結果。1 這些增益來自以不可複製型別消除參考計數、以投影型別移除跨語言複製、省去短命配置,以及讓泛型維持可特化。1

我可以閱讀那些程式碼嗎?

可以。Apple 以 MIT 授權將直譯器發布於 apple/truetype-hinting-interpreter-example,並將其描述為作為參考實作的生產級程式碼,而非持續維護的開源專案。2 那套單元測試也隨之一同釋出。1

字型直譯器為什麼攸關安全?

因為它會執行來自未受信任輸入的程式。字型透過網頁與 PDF 從任何地方傳入,而該直譯器結合了由輸入驅動的控制流程與謹慎的記憶體管理,正是記憶體損毀漏洞歷來滋生之處。1 將這個攻擊面移往一個記憶體安全的語言,便消除了整類錯誤,而文章回報,自 Swift 實作啟用以來未曾出現任何錯誤。1


這次移植印證了 Swift 工具鏈整個月來所傳遞的方向:Swift 新功能(2026)中的細粒度記憶體安全診斷、Swift 6.2 並行實務中預設高效能的並行論述,以及 Apple 對提示注入的第一方回應中載明的安全框架。完整的系列總覽請見 Apple 生態系系列

參考資料


  1. Scott Perry, Swift at Apple: Migrating the TrueType Hinting Interpreter, Swift.org blog, June 12, 2026. Source for the author’s role (Apple Security team, focusing on Swift adoption), the security framing (font parsers process untrusted data; “input-driven control flow, complex data structures, and careful memory management—exactly the kind of code that’s hard to make perfect and where memory errors are easier to exploit”), the TrueType history (developed by Apple in the late 1980s, shipped with System 7 in 1991, embeddable in PDFs in 1994 and web pages in 2008), the Fall 2025 ship date, the 13% average performance improvement measured in CPU megacycles per glyph, the no-bugs-since-enabled statement, the binary-compatibility and pixel-identical correctness requirements, the verification methodology (99.7% coverage across both implementations, the 10-million-PDF corpus fuzzer-minimized to 4,200 documents, 25,572 embedded fonts, 27 million glyphs under four transformations, nearly 4x test code), the four optimization categories (~Copyable value types and Span with back-deployment to macOS 10.14.4 and iOS 12.2; projection types over C structs after copies cost about 20% of runtime, following WebKit’s Safer Swift Guidelines with @safe and // SAFETY: comments; continuation-passing stack pops over borrowing Span; specialization and inlining guidance), the zero-cost-abstractions framing, the @objc top-level boundary (“the hot paths are fast, and the cold paths are convenient”), and the LLM-assistant instructions distilled from the migration and reused on other C/C++-to-Swift projects. 

  2. Apple, truetype-hinting-interpreter-example, GitHub, MIT license. Source for the repository’s existence, license, and its description as the Swift TrueType Interpreter, published as production code intended as a reference implementation. 

相關文章

UIKit 的 Scene 強制令:哪些情況會在 iOS 27 上無法啟動

以 iOS 27 SDK 建置的 App 必須採用 UIKit 以 Scene 為基礎的生命週期,否則將無法啟動。本文說明時程、遷移步驟與相關的 agent skill。

3 分鐘閱讀

Container Machine:在 Mac 上打造持久的 Linux 環境

Apple 的 container 工具隨著 container machine 推進到 1.0:在 macOS 上提供快速、持久的 Linux 環境,並掛載您的使用者、家目錄與 dotfiles。

4 分鐘閱讀

從76到100:達成完美的Lighthouse分數

一個個人作品集網站如何從行動裝置Lighthouse效能分數76分、CLS 0.493,進步到全類別完美的100/100/100/100。

3 分鐘閱讀