国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

.NET編譯技術內幕(2)

2024-07-10 13:02:12
字體:
來源:轉載
供稿:網友
.net編譯技術內幕(2)
作者: builder.com
tuesday, april 16 2002 12:23 pm

作為一種代碼指令平臺,microsoft .net比微軟公司先前推出的其他技術平臺要來得更為復雜。由于.net提供了對多種編程語言以及(在理論上說)多重平臺的支持,這就需要在傳統的兩個代碼層添加一個中間代碼層。在這里,傳統的兩層分別是源代碼層和編譯后的本機代碼層。新加的代碼層給.net平臺帶來了額外的靈活性,不過,反過來卻又增加了系統的復雜性。此外,由于這一新代碼層的出現,一連串的新型應用程序部署選項也首次展現在了程序員的面前。這篇文章的主旨就是引領.net應用程序的開發人員理解.net的代碼編譯過程,了解附加的編譯選項。

.net之與眾不同:msil
在microsoft .net框架內,應用程序可以用好多種高級程序語言編寫、創建,例如vb.net、c#乃至cobol .net等等都可以編寫.net應用程序。而通過每一種遵守.net規范的編程語言所編寫的程序代碼首先都得通過一種初始編譯步驟從源代碼變成.net的公共標準語言:msil(微軟中介語言:microsoft intermediate language)。msil自身是一種完整的、和對象相關的語言,只有它才可能創建出應用程序。為了大致了解msil的一些有關情況,你可以參看“通過msil語言了解clr的運行原理”一文。.net應用程序是以msil的形式出現的,只有在程序執行的時候才通過即時編譯器(jit)被編譯為本機代碼。圖a就對這一過程進行了說明。

圖a



.net的編譯過程:從源代碼到本機指令


只要裝載了assembly代碼就會進行jit編譯,可見這是一種匯編級的編譯(了解更多assembly技術的細節請參看“assembly—治愈“dll地獄”的良方?”一文)。在編譯過程中,jit編譯器一旦首次遭遇對象的索引就會裝載匹配對象各個方法聲明的對應程序。這樣,以后調用方法的時候就會編譯其il,而方法的對應根程序則被方法的編譯后代碼的地址所取代。這一過程在每次方法被首次調用的時候進行,產生的本機代碼則被緩沖以便會話過程中下次裝載assembly代碼的時候可以被使用。顯然,這樣的指令系統相比傳統的編譯語言需要更大的處理能力,不過其要求也沒有你想象的那么高。

在這里必須澄清一個普遍誤解的錯誤概念,那就是不少人認為.net應用程序是解釋型而非編譯型的程序。另外,還有這樣的常見錯誤認識:jit編譯的代碼存儲在磁盤上并且可以為同一應用程序執行。雖然這樣做也不是不可以,但是,你很快就會明白,這可不是缺省的編譯方案。應用程序的il代碼實際上在每次應用程序運行的時候都會被重新編譯為本機代碼。

兩種編譯器
事實上,jit編譯器分成兩種(經濟編譯器和普通編譯器),而且它們生來也不是平等的。經濟jit編譯器代表了運行一個.net應用程序所需要的最少功能,它直接用對等的本機代碼取代每一條msil指令,不進行任何優化從而也帶來更少的系統負載。這也意味著它主要應用在內存等資源比較緊張的平臺上。

另一方面,普通jit編譯器則是缺省的運行時配置,它會對其產生的代碼進行即時優化。這樣做無形中給予了.net超出傳統預編譯語言的一個優點:預編譯語言只能對其處理的代碼將要運行于其上的平臺做一番大致的事前估計。jit編譯器可以經過準確調節達到當前運行時狀態,結果可以完成一些預編譯語言無法完成的工作:

更高效地利用和分配cpu寄存器
在適當的情況下實施低級代碼優化,比如常量重疊、拷貝復制、取消范圍檢查、取消常規副表達式以及方法內聯等
在代碼執行期間監控當前的物理和虛擬內存需求從而更高效地利用內存
產生特定的平臺指令以準確、充分地利用實際的處理器模式

.net編譯的結果就是jit所帶來的額外負載要求并沒有產生顯著的性能損失。

性能選項
這就是說,每次運行應用程序時msil就會被jit編譯。記住,這就是常識了,然后,根據以上內容中說明的原理,在開始啟動應用程序以及首次使用非核心功能的時候顯然會導致低于優化級的系統性能表現。那么你又該采取什么措施把這種負面影響降低到最小呢?

微軟公司的對策是為我們提供了一種名為pre-jit的編譯器(也被稱做本機映像生成器:native image generator,程序名因此是ngen.exe)。從表面上看,至少它也算是應付任何性能問題的一項治療手段。pre-jit編譯器在運行時之前被調用,在安裝時,它會把全部assembly形式的msil編譯為本機代碼。這種本機代碼隨后存儲在全局assembly緩存(global assembly cache)的某一個特殊部分供以后使用,這樣就完全繞過了jit編譯過程。

乍看之下,這樣做應該是解決先前的問題了,對客戶端代碼而言尤其如此。但是,你還記得嗎?普通jit在編譯msil的時候實施了大量的即時優化操作。而許多此類的優化操作,尤其是那些牽扯到寄存器和存儲器使用的優化,都是由系統的當前需求所驅動的。所以,批量編譯assembly代碼的舉措就會阻止這些優化的進行從而在實際上產生出運行更慢的最終代碼。在你采用這個法子之前,微軟的建議是,比照普通編譯下的當前條件,把你的jit和ngen版本設置為目標平臺上的同一匯編級。

除非你是java的鐵桿擁躉,.net的運行時行為和編譯器都將同你以前曾經了解的同類情況完全不同。但是它們也不是什么神秘的東西。我希望我的闡述能澄清一些曾經令你感到迷惑的問題。菜鳥學堂:
上一篇:.NET編譯技術內幕(1)

下一篇:.Net 的一年

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 炎陵县| 固镇县| 永宁县| 虞城县| 防城港市| 监利县| 甘肃省| 蓬溪县| 荣成市| 琼结县| 宣化县| 涿州市| 山东省| 湘潭县| 叶城县| 宜州市| 仪陇县| 廉江市| 黑山县| 康马县| 峨边| 衡南县| 纳雍县| 本溪| 哈尔滨市| 正阳县| 和硕县| 鄯善县| 裕民县| 石阡县| 来安县| 漠河县| 井陉县| 武川县| 赤水市| 池州市| 阿尔山市| 长沙市| 莱西市| 双鸭山市| 城步|