首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

.NET Discovery 系列之六:JIT 編譯器深度解析(下)— 方法表、預編譯代理與 WinDbg 驗證

     編輯:關於.NET

接續上篇,詳細說明 JIT 編譯觸發流程、方法表演變與 Native Image Generator (NGen) 取捨。

JIT 編譯觸發流程

  1. 類別載入時,方法表 (Method Table/HashTable) 建立,各方法槽指向 PreJitStub(預編譯代理)。
  2. 首次呼叫方法 (如 A.a1()) 觸發 PreJitStub,呼叫 JIT 內部編譯函數(「JIT 編譯者」)。
  3. JIT 結合中繼資料與 IL 產生機器碼,存入動態記憶體,修改方法表對應槽位為機器碼入口位址。
  4. 後續呼叫直接跳轉機器碼,不再經 JIT。

觸發 JIT 編譯示意 再次呼叫不觸發 JIT 方法表/預編譯代理關係

MSCorEE 與 mscorwks 核心職責

  • 查找組件類型清單、遍歷方法中繼資料。
  • 取得方法 IL、配置記憶體。
  • 編譯 IL 為機器碼、修正方法表入口。
  • 跳轉執行機器碼。

WinDbg + SOS 實測驗證

  1. 附加進程、載入 SOS.dll。
  2. !name2ee *!JITTester.A 查看類型資訊。
  3. 按鈕觸發 new A().a1() 前:方法表顯示 <not loaded yet>(未 JIT)。
  4. 觸發後重新查看:方法表更新為實際記憶體位址,Stub 被跳轉指令取代。
  5. 未呼叫的類別 (B) 仍顯示未載入;因建構 A 時實例化 C,故 C 已 JIT。

JIT 前 A 類型 JIT 後 A 類型 B 類型未 JIT C 類型已 JIT

NGen.exe:慎用

NGen 產生完整原生映像安裝至 GAC,啟動時載入整個映像而非按需 JIT。缺點:

  • Framework/CPU/OS 變更即失效回退 JIT。
  • 仍需發布 IL 與中繼資料。
  • 忽略局部性原理,整體載入佔記憶體,可能需重定位。
  • 無法運行時優化、無法跨 AppDomain 共用組件。
  • JIT 具備程式碼換出、記憶體壓力平衡能力,嵌入式裝置尤重要。

除非確定啟動效能瓶頸在首次 JIT,否則優先信任 JIT。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved