.Net Discovery 系列之六–深入淺出.NetJust-In-Time 編譯機制(下)

來源:互聯網
上載者:User

    接上文

    在初始化時,HashTable中各個方法指向的並不是對應的記憶體入口地址,而是一個JIT先行編譯代理,這個函數負責將方法編譯為本地代碼。注意,這裡JIT還沒有進行編譯,只是建立了方法表

    下表(表1)為首次載入調用時HashTable的情況:

                     表1 方法表示意

方法槽

方法描述

a1()

PreJitStub

a2()

PreJitStub

a3()

PreJitStub

    好了有了這個HashTable後,JIT開始編譯第一個被調用的方法A.a1("First"),這是由一個JIT內建函式來完成的(上面提到的),遺憾的事,目前還沒有發現介紹這個函數的相關資料,有些書中稱它為“JIT編譯者”,那本文也這麼稱呼它吧。

    為首次調用方法時的:

 

 

圖2 觸發JIT編譯

    JIT藉助中繼資料和IL產生被呼叫者法的本地代碼後,會將這些代碼緩衝在動態記憶體中,然後修改HashTable中對應方法的入口地址,將其修改為本地代碼的記憶體片地址(如表2所示),並將這個地址返回給CLR經行執行,A.a1("First")執行完畢,代碼繼續運行。

    運行至A.a1("Second ")時,會直接執行A.a1()方法的記憶體代碼,不會進行再次編譯,表2 為再次載入時HashTable的情況。

              表2 方法表變化

方法槽

方法描述

a1()

XXXXXXXXX記憶體位址

a2()

PreJitStub

a3()

PreJitStub

    再次載入流程:

 

圖3 未觸發JIT編譯

 

 

圖4 方法表、方法描述、先行編譯代理關係

 

    圖2中所示的MS核心引擎指的是一個叫做MSCorEE的DLL,即Microsoft .NET Runtime Execution Engine,它是一個橋接DLL,連同mscorwks.dll主要完成以下工作:

  1. 尋找程式集中包含的對應類型清單,並調用中繼資料遍曆出包含的方法。
  2. 結合中繼資料獲得這個方法的IL。
  3. 分配記憶體。
  4. 編譯IL為本地代碼,並儲存在第3步所分配的記憶體中。
  5. 將類型表(就是指上文中提到的HashTable)中方法地址修改為第3步所分配的記憶體位址。
  6. 跳轉至本地代碼中執行。

    所以隨著程式的已耗用時間增加,越來越多的方法的IL被編譯為本地代碼,JIT的調用次數也會不斷減少。

      下面藉助WinDbg來證實以上的說法,樣本中的來源程式可以到這裡下載到:

      http://files.cnblogs.com/isline/IsLine.JITTester.rar

 

namespace JITTester

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}



private void Form1_Load(object sender, EventArgs e)

{



}



private void GO_Click(object sender, EventArgs e)

{

new A().a1();

lb_msg.Text = "調用完畢!";



}

}



class A

{

public void a1() { }

public C a2 = new C();

}



class B

{

public void b1() { }

public void b2() { }

}



class C

{

public void c1() { }

public void c2() { }

}

}

 

      代碼中定義了3個類,分別為A、B、C,在“GO”按鈕按下後,將調用類型A中的a1()方法,而Form1_Load 中什麼也不做,目的是程式運行後,在空載的情況下查看方法描述對應地址入口的情況。

    好,第一步運行JITTester.exe程式,並開啟WinDbg附加這個進程

 

圖 5 附件進程

 

   第二步,附加進程成功後,在WinDbg中載入SOS.dll

 

圖6 載入SOS.dll

    第三步,使用name2ee命令遍曆所有已載入模組,name2ee格式為name2ee *! [程式集].[類型]

 

圖7 查看類型資訊

    斷行符號後注意高亮地區的資訊:

 

圖8 JIT前A類型的資訊

    高亮地區顯示的是“<not loaded yet>”,這說明雖然運行和程式,但未點擊按鈕時,A類型未被JIT,因為它還沒有入口地址。這一點體現了即時、按需編譯的思想。

   同樣,!name2ee *!JITTester.B和!name2ee *!JITTester.C命令會得到同樣的結果。

    好,現在做第4步操作,Detach Debuggee進程,並回到程式中點擊“GO”按鈕

 

 

圖9 點擊按鈕

 

    第五步 重新附加進程(參考第一步),這時程式已經調用了new A().a1()方法,並重新執行命令!name2ee *!JITTester.A ,注意高亮部分

 

圖10 JIT後A類型的資訊

    和圖8中的資訊比較,圖10中的方法表地址已經變為JIT後的記憶體位址,這時圖4中的Stub槽將被一條強制跳躍陳述式替換,跳轉目標與該地址有關。這一點說明JIT在大多情況下,只編譯一次代碼。

    同樣命令查看B類型:

 

圖11 JIT後B類型的資訊

    該類型未被調用,所以還未被JIT。

    C類型:

 

圖12 JIT後C類型的資訊

 

    由於執行個體化A類型時和C類型相關,所以C類型已經JIT了。

    第三節.Native Image Generator

    Native Image Generator中文譯為本地代碼產生器,我更習慣叫它“本地映像”,因為通過工具NGen.exe產生的本地代碼是無法部分載入的,這意味著作業系統會載入整個組件檔。

    上一節中提到過,有兩種方法可以獲得本地代碼,JIT方式和Native Image Generator方式,JIT方式是在運行時動態編譯需要的代碼,而NGen.exe會建立託管程式集的本機映像,並且將該映像安裝到GAC中,運行該程式集時,就會自動使用該本機映像而不是JIT它們。

這聽起來似乎很美妙,但是你必須做好以下準備:

  1. 當FrameWork版本、CPU類型、作業系統版本發生變化時,.Net會恢複JIT機制。
  2. NGen.exe工具並不能避免發布IL,事實上,即使使用NGen.exe工具,CLR依然會使用到中繼資料和IL。 
  3. 忽略了局部性原理(上一節中提到的),系統會載入整個映像檔案到記憶體中,並很可能重定位檔案,修正記憶體位址引用。 
  4. NGen.exe產生的程式碼無法在運行時進行最佳化,無法直接存取靜態資源,也無法在應用程式定義域之間共用組件。 

    此外,JIT不但有編譯的本事,還會根據記憶體資源情況換出使用率低的代碼,節省資源,這對於一些基於.Net平台的電子產品是很重要的。 

    所以,除非你已十分清楚程式效能是由於首次編譯造成的效能問題,否則盡量不要人工產生本地代碼。 

 

    我是李鳴(Aicken) 請您繼續關注我的下一篇文章。

 

    “.Net Discovery 系列”推薦:

     .Net Discovery 系列之五--Me JIT(上)

     .Net Discovery 系列之三--深入理解.Net垃圾收集機制(上)

     .Net Discovery 系列之四--深入理解.Net垃圾收集機制(下)

     .Net Discovery 系列之一--string從入門到精通(上)

     .Net Discovery 系列之二--string從入門到精通(下)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.