一、CLR首次加載代碼形成的性能損失 html
4、CLR執行程序集中代碼介紹了CLR在首次執行一個類的時,會初始化一個內部結構,而後當目標方法被首次調用時,JITComplier函數(JIT編譯器)會驗證IL代碼並將IL代碼編譯成本地CPU指令並存儲到動態內存中,這意味着一旦應用程序終止,編譯好的代碼也會被丟棄,因此,當再次運行應用程序,或者同時啓動應用程序的兩個實例(使用兩個不一樣的操做系統的進程),JIT編譯器必須再次將IL編譯成本機指令.對於某些應用程序,這可能會增長內存的負擔.後端
相比之下,本機(native)應用程序的只讀代碼頁可由應用程序正在運行的全部實例共享.函數
二、CLR首次加載代碼形成的性能損失的嚴重程度工具
對於大多數應用程序,JIT編譯形成的損失並不嚴重,大多數應用程序都在反覆的調用相同的方法。應用程序運行期間,這些方法只會對性能形成一次性的影響.除此以外,在方法內部花費的時間可能比花在首次調用方法,JIT編譯和優化IL所花費的時間更多.性能
三、CLR加載代碼時JIT編譯器進行的代碼優化優化
CLR首次加載程序集代碼時,JIT將IL編譯成本地代碼時,會對其進行代碼優化,這相似與非託管C++編譯器的後端所作的事情.這可能也會花費加多的時間生成優化代碼.spa
(1)、編譯器開關/optimize和/debug對代碼的影響操作系統
/optimize開關:debug
C#編譯器生成的未優化IL代碼,將包含許多NOP(空操做)指令,還將包含許多跳轉到下一行代碼的分支指令.Visual Stdio利用這些指令在調試提供"編輯並繼續"功能.另外,利用這些額外的指令,還可在控制流程指令(好比for,while,do,if,else,try,catch和finally)上設置斷點,使代碼更容易調試.相反,若是生成優化的IL代碼,C#編譯器會刪除多餘的NOP和分支指令,而在控制流程被優化以後,代碼就不能再調試器中進行單步調試了。代碼若在調試器中執行,一些函數求值可能沒法進行.可是,優化過的IL代碼變得更小,結果EXE/DLL文件也更小.調試
/debug(+/full/pdbonly)開關:
編譯器會生成Program Database(PDB)文件,PDB文件幫助調試器查找局部變量並將IL指令映射到源代碼.
/debug:full開關告訴JIT編譯器你打算調試程序集,那麼JIT編譯器會記錄每條IL指令所生成的本機代碼.這樣依賴,就可利用Visual Studio的「即時」調試功能,將調試器鏈接到正在運行的進程,並方便地對源代碼進行調試.
不打開/debug:full開關,JIT編譯器默認不記錄IL與本機代碼的聯繫,這使JIT編譯器運行的稍快,佔用內存也稍少.若是進程用Visual Stdio的「即時」調試功能,會強迫JIT編譯器記錄IL與本機代碼的聯繫(不管編譯器的開關設置是什麼)除非在Visual Stdio中關閉了"在模塊加載時取消JIT優化(權限託管)"操做步驟以下:
工具-選項-調試
(2)、Visual Stdio中新建C#項目時,編譯器開關的默認設置
經過VS新建項目時,項目的調試(Debug)配置的是/optimize-和debug:full開關(IL代碼和本地代碼均未優化-方便調試),而"發佈"(Release)配置置頂的是/optimize+和/debug:pdbpnly開關(IL代碼和本地代碼均優化-文件變小,佔用內存小)