跳至內容

即時編譯

出自Taiwan Tongues 台語維基
這是此頁批准,以及是最近的修訂。

佇咧電腦技術當中,即時編譯(英語:Just-in-time compilation,縮寫為JIT;閣譯及時編譯即時編譯), 嘛叫做動態翻譯抑是執行的時編譯,是一種執行電腦代碼的方法,這種方法設計佇程式執行過程中(咧執行期)毋是佇咧執行進前進行編譯。通常,這包括原始碼或者是閣較捷看著的位元組碼到機器碼的轉換,然後直接執行。實現 JIT 編譯器的系統通常會不斷就會分析當咧執行的代碼,並確定代碼的某一寡部份,佇咧這个部份內底,編譯抑是重新編譯所得著的加速將超過編譯該代碼的開銷。

JIT 編譯是兩種傳統的機器碼翻譯方法—— 提前編譯(AOT)佮直譯器—— 的結合,伊結合兩个人的優點佮缺點。大概來講,JIT 編譯,以直譯器的開銷猶閣有編譯佮連結(解說以外)的開銷,結合了編譯代碼的速度佮解說的靈活性。JIT 編譯是動態編譯的一个形式,允准自適應最佳化,比如動態重編譯佮特定佇微架構的加速—— 所以,佇理論上,JIT 編譯比靜態編譯會當產生閣較緊的執行速度。解說佮 JIT 編譯特別適合動態程式語言,因為執行的時系統會當處理後期結束的資料類型並實施安全保證。

應用

JIT 編譯會當應用某一寡程式,原仔會當用佇某一寡能力,特別是動態能力,如正規表示式。比如講,一个文字編輯器會當共執行的時提供的正規表示式編譯做機器碼,因為自按呢開始進行匹配—— 這袂當提前完成,因為乎 pattern 干焦佇執行的時提供。一寡現代的執行時環境依賴 JIT 編譯來實現高速代碼執行,包括大多數 Java 實現,猶閣有微軟仔 . NET 框架。類似地,真濟正規表示式庫攏有對正規表示式來進行 JIT 編譯的功能,會當編譯做位元組碼,原仔會當編譯做機械碼。JIT 編譯嘛用一寡模擬器當中,以便將機器碼對一个 CPU 體系結構換著另外一个 CPU 體系結構。

JIT 編譯的一个捷見實現是首先進行 AOT 編譯,共原始碼編譯做位元組碼(虛擬機器代碼), 這號做位元組碼編譯,才閣將 JIT 編譯做機械碼(動態編譯), 毋是解說位元組碼。佮解說相比,這提懸矣執行的時效能,猶毋過代價是編譯造成的延遲。佮直譯器仝款,JIT 編譯器不斷咧進行翻譯,猶毋過對編譯了後的代碼進行緊取會當上大限度地減少予定執行期間將來執行仝款代碼的延延。

概述

佇位元組碼編譯的系統當中,原始碼予人轉換做是位元組碼的中央表示形式。位元組碼毋是任何特定電腦的機器碼,會當佇電腦架構之間徙栽。然後會當佇虛擬機器頂懸解說或執行位元組碼。JIT 編譯器佇濟濟的部份(抑是全部、真少)讀取位元組碼,閣共動態編做機械碼,通好用程式會當較緊咧執行。這會當針對每一个檔案、逐个函式甚至任何任意代碼片段進行編譯;代碼會當佇咧欲執行的時進行編譯(所以講呢「即時」), 紲落緊取佇後擺重用,不需要重新編譯。

比並之下,傳統的解說型虛擬機器干焦解說位元組碼,通常效能愛低足濟。有的直譯器甚至無需要頭先編譯做位元組碼就會當解說講原始碼,但效能閣較䆀。靜態編譯的代碼抑是本地代碼佇部署進前編譯。動態編譯環境是咧執行期間會當使用編譯器的環境。 使用 JIT 技術的一个共同目標是達到或者是超過靜態編譯的效能,同時保持位元組碼解說的優勢:解破原始原始碼佮執行基本最佳化的誠濟「繁重的工課」通常是咧編譯時處理的,佇部署進前:對位元組碼編譯到機器碼愛比對原始碼編譯得欲多。佮本地代碼無仝,部署的位元組碼是會當徙栽的。因為執行的時陣會當控制編譯,比如解說一个位元組碼,所以伊會當佇安全的沙箱內底執行。對位元組碼到機器碼的編譯器閣較容易編寫,因為會當紮式位元組碼編譯器已經完成矣大部份工課。

JIT 代碼通常比直譯器效能閣較好。另外咧,佇某一寡狀況下,伊的效能會當比靜態編譯較好,因為真濟最佳化只有咧執行的時陣會當:

一 . 編譯會當針對目標 CPU 佮應用程式執行的作業系統模型進行最佳化。比如講,JIT 會當佇檢測著 CPU 支援 SSE 二向量 CPU 指令的時陣選擇𪜶。愛使用靜態編譯器得著這種最佳化級別的特殊性,著愛為著一个預期的平台 / 體系結構編譯一个二進位檔案,或者是佇一个二進位檔案當中包含真濟个版本的部份的代碼。 二 . 這个系統乎會當收集關於程式佇咧其所佇咧環境中實際執行的這个情況的這个統計資訊,並且會當重新排列佮重新編譯以得著最佳效能。毋過一寡設計編譯器嘛會當將概愛資訊做為輸入。 三 . 這个系統會當進行全域代碼最佳化(譬如講行內庫函式), 同時無失去動態連結的優點,嘛袂失去靜態編譯器佮連結器原生的開銷。具體來講,佇進行全域行內替換的時陣,靜態編譯過程可能需要執行的時檢查,並且確保若是物件的實際類有重寫行內方法,就會虛擬呼叫,而且對陣列存取的邊界條件檢查可能需要佇迴圈中處理。佇真濟情形下,使用即時編譯,這款處理會當對迴圈內底徙出,通常會大咧提高速度。 四 . 就算使用靜態編譯的糞埽收集語言會當做到這點,但是元組碼系統會使閣較容易地重新排列執行的代碼,以得著閣較好的緊取利用率。

因為 JIT 必須愛佇咧執行的時陣呈現佮執行本地二進位映像,所以講真正的機器碼 JIT 需要允准佇執行的時執行資料的平台,這使得佇咧基於哈佛結構的機器頂頭使用這種 JIT 成做無可能的代誌—— 對某寡作業系統佮虛擬機器嘛是按呢。毋過,一種特殊類型的「JIT」可能並無針對物理機器的 CPU 體系結構,是一種最佳化的 VM 位元組碼,佇這个情形下,對原始機器碼的限制占上風,特別是佇咧位元組碼的 VM 最後欲共 JIT 用佇本機代碼的情形下。

啟動延遲和最佳化

因為載入佮編譯位元組需要的時間,JIT 佇咧應用程式的初初執行中會致使輕微到明顯的延遲。有時這種延遲予人稱做「啟動的時間延遲」抑是「注文時間」。 一般來講,JIT 執行的最佳化愈濟,生的代碼就愈好,但是初初延延嘛會增加。所以,JIT 編譯器必須佇咧編譯時間佮希望生成的代碼品質之間進行權衡。除了 JIT 編譯以外,IO 結操作嘛會增加啟動時間按呢:比如講,JVM 的「rt . jar」類的資料檔案為四十 MB,JVM 必須佇這个大摸的頂下文檔案當中走揣大量的資料。

Sun 的 HotSpot Java 虛擬機器使用的一種可能的最佳化方法是欲解說佮 JIT 編譯共合起來。應用程式代碼上頭仔是予人解說的,猶毋過 JVM 監視佗一寡位元組碼序列定定被執行,並且共轉換做機器碼,以便若硬體上直接執行。嘿干焦執行幾擺的位元組碼,這節省了編譯時間閣減少初初;對頻繁執行的位元組碼,JIT 編譯用佇咧沓沓仔解說的初始階段了後用高速執行。此外,因為程式開足濟時間執行其實只是一寡細部份的代碼,所致減少的編譯時間真重要。最後咧,佇初初代的大概解說期間,會當佇編譯進前收集執行統計資訊,這對執行誠好的最佳化。

正確的權衡會當根據具體的情形來變化。比如講,Sun 的 Java 虛擬機器有兩種主要的模式:客戶機和侍服器。佇客戶捀模式下,執行上細程度的編譯佮最佳化,以減少啟動時間。咧侍服器的方式,共執行大量的編譯佮最佳化,以犧牲啟動的時間來上大限度地提懸應用程式執行時的效能。其他 Java 即時編譯器使用一個方法執行次數的執行時度量,結合方法的位元組碼大細做為一種啟發式方法來決定當時編譯。閣有的使用執行的次數佮檢測迴箍相結合。一般來講,佇咧短期執行的應用程式內底確定預測欲最佳化的方法愛比佇咧長期執行的應用程式內底確確甲濟。

微軟的本地鏡親像生成器(Ngen)是另外一種減少初初延的方法。Ngen 共通用中央語言影像中的位元組碼預編譯做機器本機代碼。所以,無需要執行的時編譯。Visual Studio 兩千空五附帶的 . NET Framework 二嬸空佇安裝了後隨佇所有微軟庫 dll 上執行 Ngen。預 JIT 提供一種提懸啟動的時間的方法。猶毋過,伊生的代碼品質可能不如 JIT 生成的代碼品質好,原因佮靜態編譯的代碼(無按組態最佳化)佇極端的狀況之下不如 JIT 編譯的代碼的原因仝款:無分析資料來驅動,比如講,行內快取。

閣有一寡 Java 實現將 AOT 編譯器佮 JIT 編譯器(Excelsior JET)直譯器(GNU Compiler for Java)敆起來。

歷史

上早發布的 JIT 編譯器通常歸功於約翰 ・ 麥卡錫佇一九六零年著 LISP 的研究。佇伊的重要論文《符號表達式的遞迴函式和其在機器上的計算》(Recursive functions of symbolic expressions and their computation by machine , Part I)第一部份內底,伊講著矣咧執行的時陣去予轉換的函式,所以無需要儲存編譯器輸出來拍空卡(雖然閣較準確的講法是「編譯閣執行系統」)。 另外一个古早的應用來自肯 ・ 湯普遴,伊佇咧文字編輯器 QED 的正規表示式模式匹配當用矣 JIT。為著提高速度,Thompson 佇相容分時系統上通過 JIT 到 IBM 七千空九十代碼實現矣正規表示式匹配。一九七空年,Mitchell 首創了一種有影響力的對解說中取得編譯代碼的技術,伊佇實驗語言 LC² 中實現這種技術。

Smalltalk(一九八三年)開創矣 JIT 編譯的新領域。比如講,需要翻譯做機器碼,緊取結果以供了後使用。做記持體不足的時陣,系統會刪除部份代碼,而且需要時間重新生成。Sun 的 Self 語言廣泛地改進了遮的技術,是世界上速度上緊的 Smalltalk 系統;運用完全物件導向的語言實現矣懸達到最佳化 C 語言一半的速度。

Self 予被 Sun 放捒矣,但是研究轉向矣 Java 語言。「即時編譯」這術語是對製造術語「到時」著借來的,並由 Java 普及,James Gosling 對一九九三年開始使用這个術語。目前,大多數啦 Java 虛擬機器的實現攏使用 JIT 技術,因為乎 HotSpot 建立佇這个研究基礎之上,而且使用廣泛。

HP 的這个案 Dynamo 是一个實驗性的 JIT 編譯器,其位元組碼格式佮機器碼格式是仝款的;該系統將 PA 抹六千機器碼轉換做 PA 鋪八千機器碼。佮直覺相反,這致使著速度的提懸,佇某一寡狀況下是百分之三十,因為按呢做允准佇機器碼級別進行最佳化,比如講,行內代碼以閣較好的地使用緊取,最佳化對動態庫的呼叫,閣有真濟其他定規編譯器無法度試的執行的時最佳化。

二空一九年三月三十,PHP 宣佈 JIT 欲佇二空二一年加入 PHP 八。

安全

JIT 編譯對根本上使用會當執行資料,所以有𤆬來安全的挑戰佮可能的空縫。

JIT 編譯的實現包括將原始碼或者是位元組碼編譯做機器碼並執行伊。這通常是直接佇記憶體內底完成的—— JIT 編譯器將機器碼直接輸出到記憶體中並且隨執行,毋是像通常的進前編譯按呢共其輸出到磁碟,才來做單獨的程式呼叫代碼。佇現代的體系結構當中,因為可能執行空間保護,按呢拄著一个問題—— 無法度佇任意記持體內底執行程式。佇任意記持體內底執行程式存在藏佇安全漏洞。所以,必須愛將記憶體標記做有可執行;出於安全原因,應該佇咧代碼寫入記憶體並標記做唯讀了後執行,就因為會當寫 / 會當執行記持體是一个安全漏洞(參見 W ^ X)。 比如講 Firefox 的 JavaScript 的 JIT 編譯器佇咧 Firefox 四十六版本內底引入著這款保護。

JIT 噴射是一種利用漏洞利用的技術,伊使用 JIT 編譯進行堆噴射—— 生成的記持體然後是會當執行的,若執行會當徙去堆積牢咧,這就允准利用。

參見

  • 二進位翻譯
  • HotSpot
  • 通用語言運行庫
  • Crusoe,一種微處理器,基本上執行對 x 八十六代碼碼小可處理器內部微碼的即時編譯
  • GNU lightning—一个咧執行時生成組合語言代碼的庫
  • LLVM
  • 自修改代碼
  • 跟蹤即時編譯
  • 動態編譯

注釋

參考文獻

參照

來源

外部連結

  • 自由線頂電腦詞典的詞條
  • Mozilla Nanojit—一个小型的會當產生機器碼的迒平台 C + + 庫。伊予人用作 Mozilla Tamarin 和 SpiderMonkey Javascript ia̋n-jín 的 JIT。
  • OVPsim,一種1875入式的核心 JIT 工具,伊將 ARM、MIPS 佮其他 ISA 指令轉換做 x 八十六進行執行 / 類比
  • 使用「VTune 效能剖析器」評測執行的時生成佮解說的代碼