Ngen生成Native代碼實戰及優缺點分析

 

      先科普一下,.Net是一個用於Windows的託管代碼模型,用於高效構建具備視覺上引人注目的用戶體驗的應用程序。但這個模型生成的代碼並不是可執行代碼,而是由.Net公共語言運行庫環境執行的IL代碼。因此,每次執行代碼時,都會由.Net將IL代碼翻譯爲機器代碼。因此,效率上天然會受到必定影響。對此,微軟在.Net中附帶一個將IL代碼轉換爲Native代碼的工具Ngen.exe。它能夠建立一份程序集文件至相似於C:\WINDOWS\assembly\NativeImages_v4.0.30319_32的文件夾內。這個文件夾下一般會包含以下信息:dom

            1.公共語言運行庫的版本函數

            2.x64版本或x86版本信息(包括x86,x64和Itaninum)工具

            3.Native代碼性能

      若是這樣一個Ngen程序集被建立了(暫且這麼叫它),那麼,CLR載入程序集文件時,就不會實時編譯,而會使用Ngen程序集中的代碼,因而,應用程序集的啓動速度、運行速度都獲得了提高。優化

      看起來很美好,是吧(哪一種技術聽起來不美好…)?既獲得了託管代碼的全部優勢,還獲得了近似於普通非託管代碼的執行性能咱們先來分析一下它的優缺點:ui

Advantage:1.提升啓動速度, 由於代碼已經編譯成Native代碼, 因此在運行時就不須要編譯了。翻譯

                2.減小應用程序的工做集,若是一個程序集會被同時載入到多個進程/Appdomain,,在這個程序集上運行Ngen能減小應用程序的工做集。由於Ngen會將IL編譯爲Native代碼後,保存到單獨的文件夾。這個文件夾能在同一時刻對多個進程空間起做用,且容許代碼共享。因此, 每一個進程/AppDomain沒必要爲本身拷貝一份代碼。debug

Disadvantage:1.編譯Native代碼後,原IL代碼不可刪除。由於運行的時候,CLR須要訪問程序集的metadata,這須要IL與Native二者。且不少人認爲發佈Native代碼就能夠避免IL原始代碼泄露,以保護知識產權,其實這是錯的。orm

                     2.NGen文件可能會過期: 當CLR載入NGen所映射文件時,,它會比較之前編譯的代碼和當前的執行環境的不少特徵, 若是任何特徵不匹配,預編譯的文件就不能被使用, JIT編譯器進程就要使用。下面必須被匹配的部分特徵列表:進程

                     ① 程序集模塊的版本ID (MVID)

                     ② 被引用的程序集的版本ID

                     ③ 處理器類型

                     ④ CLR版本

                     ⑤ Build類型(release, debug, optimized debug, profiling, 等等)

                     若預編譯程序集過期,能夠以升級的方式運行Ngen.exe來補救, 這告訴工具對之前曾經被執行Ngen操做的全部的程序集上運行Ngen。當終端用戶安裝.NET Framework的一個新service pack,,那麼service pack的安裝程序將會在更新模式下自動運行Ngen.exe, 使得NGen文件保持和CLR的版本一致。

                     4. 較差的載入時性能(重定位/綁定): 程序集文件還是標準的Windows PE文件, 每一個文件包含着一個優先使用的基地址。 CLR會對於內存地址進行計算,致使額外的性能消耗。然而, Ngen程序集文件的一些內存地址引用是靜態計算的, 當Windows加載一個Ngen文件時, 它檢查文件是否被載入到優先的基地址上, 若是文件沒有載入到優先的基地址, Windows會從新定位文件, 修改全部內存地址引用。這是極其耗時的, 由於Windows必須載入整個文件, 並修改文件中的不少字節. 此外, 這個頁面文件對應的代碼不能跨進程邊界共享。

                     5. 較差的執行時性能: 當編譯代碼時, Ngen對執行環境作出的假設不會比JIT編譯器的多, 這會形成Ngen產生較保守的代碼, 例如, Ngen不能優化一些CPU指令。 Ngen處處插入代碼來調用類的構造函數, 由於它不知道代碼執行的次序, 不知道類的構造函數是否已經被調用了。 一些Ngen應用程序反而會比JIT編譯的代碼慢大約5%, 所以, 若是你打算使用Ngen來提升應用程序的性能, 你應該對比Ngen和非Ngen版本的應用程序, 肯定Ngen版本在實際執行時並不慢。 對於一些應用程序, 減少的工做集大小會提升性能, 所以Ngen整體上仍是會取勝。

      Ngen的利弊,須要你們本身去權衡,但對於客戶端應用程序,Ngen會對於提升啓動速度或者減少工做集有幫助。此外,若是Ngen被用於全部的客戶端應用程序的程序集, 那麼CLR就根本不須要載入JIT編譯器, 從而更進一步地下降了工做集. 固然, 若是隻有一個程序集不是Ngen所建立或者若是一個程序集的Ngen文件不能被使用, JIT編譯器就會被載入, 應用程序的工做集將會增長。

      如何使用Ngen呢?很簡單咱們只須要兩個命令就能夠玩轉它,這兩個命令是

      Ngen install filepath

      Ngen uninstall filepath

      當咱們想建立一份Ngen程序集時,只要按以下步驟作:假設E盤內有一個WindowsFormsApp.exe文件,它屬於WindowsFormsApp工做集。打開命令提示符,輸入「cd C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319」(目錄因Windows、.Net版本而異),回車。再輸入「Ngen install e:\WindowsFormsApp」,回車。這樣,一份Ngen工做集就在本地建立完成了。固然想卸載它,只要輸入「Ngen uninstall e:\WindowsFormsApp」,回車便可。

      固然,這只是本地Ngen工做集,要在客戶機上建立,必需要在安裝軟件中加入Ngen代碼。

相關文章
相關標籤/搜索