執行你的程式集代碼

來源:互聯網
上載者:User

前面提到, 託管的程式集包含著metadata和中繼語言(IL), IL是一個獨立於CPU的機器語言, 是微軟與幾家外部商業和學術的語言/編譯器作者協商之後開發的. IL是比絕大多數CPU機器語言進階的語言, IL能夠訪問和操作物件類型, 能夠建立和初始化對象, 調用對象的虛函數, 能直接運算元組元素, 它甚至還能為錯誤處理拋出和捕獲異常. 你可以把IL想象為一個物件導向的機器語言.

通常, 開發人員編寫進階語言, 例如C#,C++/CLI, 或者VB. 為這些進階語言工作的編譯器將產生IL. 然而, 像其它機器語言, IL可以用組合語言來編寫, 微軟確實提供了一個IL彙編器, ILAsm.exe, 還提供了一個IL反組譯碼器ILDasm.exe.

記住任何層次的語言很可能只暴漏出CLR提供的一部分功能. 然而, IL組合語言允許開發人員訪問所有的CLR功能. 因此, 如果你選擇的程式設計語言隱藏了部分CLR的功能, 你可以用IL組合語言編寫那部分代碼, 或者利用其他具有你需要的CLR功能的程式設計語言.

獲得CLR提供的功能的唯一方式是閱讀CLR文檔, 在本書, 我儘力關注CLR功能, 以及如何被C#語言暴露的(或沒有暴露). 我懷疑其他書籍或者文章只是通過一種語言來闡述CLR的功能, 使得大多數開發人員理解CLR只提供了那種語言所對應的那部分功能. 只要你的語言允許你完成你想做的事情, 那麼這種模糊的看法也不是件壞事.

重要: 我認為這種方便在語言之間進行切換和切換的能力是CLR一個很強大的功能. 不幸的是, 我也認為開發人員將會更加忽視這個特性. 像C#和VB這樣的程式設計語言對於執行I/O操作是非常優秀的語言. APL對於執行進階工程或商務計算是非常優秀的語言. 通過CLR, 你可以用C#編寫你的應用程式的I/O操作部分, 用APL編寫工程計算的部分. CLR提供了這些語言之間整合的層次, 這是前所未有的技術, 這使得混合語言編程值得許多開發項目考慮.

為了執行一個函數方法, 它的IL必須被轉換成native CPU指令, 這是CLR JIT(just-in-time)編譯器的工作.

給出了一個函數方法第一次被調用所發生的事情:

在執行Main函數之前, CLR檢測被Main的代碼所引用的所有類型, 這導致CLR分配內部的資料結構用於管理被應用類型的訪問. 在中, Main函數引用一個類型, Console, 導致CLR分類一個內部結構, 這個內部資料結構為Console類型定義的每個方法包含一個條目, 每個條目包含方法實現的地址. 當初始化這個結構時, CLR設定這些條目到一個內部的沒有文檔描述的函數(CLR內部), 我們稱這個函數為JIPCompiler.

當Main函數第一次調用WriteLine時, JITCompiler函數被調用, JIPCompiler函數負責編譯一個函數的IL為native CPU指令. 因為IL是在”just in time”時編譯的, 這個CLR組件也常稱為JITter或者JIT Compiler.

注意: 如果應用程式運行在x86版本的Windows或者WoW64上, JIT Compiler將產生x86指令, 如果應用程式以64位應用程式運行在x64或者IA64版本的Windows上, JIT Compiler將產生x64或者IA64指令.

在調用時, JITCompiler函數知道正在調用的是什麼函數, 知道這個函數的類型. JITCompiler函數然後在程式集的metadata中搜尋被呼叫者法的IL. 然後JITCompiler驗證和編譯IL代碼為native CPU指令, native CPU指令被儲存在動態分類的記憶體塊中. 然後JITCompiler返回到被調用函數的條目上(在CLR建立的類型的內部資料結構), 並替換那個引用為包含剛才編譯為native CPU指令的記憶體塊的地址. 最後, JITCompiler函數跳到記憶體塊的代碼處, 這個代碼就是函數WriteLine的實現(接受String參數的版本). 當這個代碼返回時, 它返回到Main中, 然後繼續正常執行.

Main現在第二次調用WriteLine函數, 這次, WriteLine的代碼已經被驗證和編譯了, 因此調用直接轉到記憶體塊, 完全跳過了JITCompiler函數, 當WriteLine函數執行完之後, 它就返回到Main函數. 給出了第二次調用WriteLine函數的過程:

 

函數只有在第一次調用時有效能上的損失, 隨後的調用是全速執行native代碼, 因為不需要對native代碼進行驗證和編譯.

JIT compiler將native CPU指令儲存在動態記憶體中, 這意味著被編譯的代碼在程式終止時將被拋棄, 因此如果你再次運行應用程式, 或者同時運行兩個應用程式執行個體(在兩個不同的作業系統進程), JIT compiler將再次將IL編譯為native指令.

對大多數應用程式來說, 由JIT編譯所導致的效能下降不是很重要, 多數應用程式常常是重複調用相同的函數, 這些函數在應用程式執行時只有一次效能上的下降, 容易看出花在函數內部的時間比調用的時間長的多.

你應該也注意到CLR的JIT編譯器最佳化了native代碼, 這類似於非託管的C++編譯器在後端所作的工作, 它可能需要更多的時間來產生最佳化的代碼, 但是最佳化過的代碼比沒有被最佳化的代碼執行的更快.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.