CLR Via讀書筆記第一章(3)CLR執行程序集的IL代碼

在瞭解CLR運行以前讓咱們先簡單瞭解一下IL服務器

除了編譯器編譯的IL代碼,IL也是一種彙編語言,也就是說咱們能夠直接編寫IL代碼,固然也有對應的IL編譯器,值得一提的是對於面向CLR的其餘語言,
CLR只開放了一部分功能,而IL能夠訪問CLR的所有功能。數據結構

前面一章咱們介紹了CLR的全部初始工做,最後在調用Main入口方法的時候,CLR須要將程序集中的IL代碼轉爲CPU指令,也就是CLR中JIT(just-in-time)
編譯器的職責,CLR會即時編譯IL代碼函數

即時編譯:在運行的時候纔會進行編譯(相似懶加載)
當CLR運行並調用方法時作了以下幾件事情
  一、檢測出全部方法中全部被引用的類型,並建立一個內部數據結構進行管理,每一個類型的方法都會記錄指向名爲JITComplier函數的地址,
  二、在方法被調用的時候,函數會在與元數據中查找被調用的方法對應的IL代碼,對其驗證並將代碼編譯成CPU指令
  三、將CPU指令存貯到動態分配的內存中
  四、回到內部數據結構中,修改對應方法記錄的地址,指向剛纔編譯好的CPU指令的地址
  五、最後函數會回到內存當中去運行CPU指令工具

圖片描述

至此一個方法調用的所有流程就走完了,若是不終止程序(終止會將編譯好的cpu指令丟棄),那麼CLR在第二次調用方法時,直接在數據
結構中找到對應的內存運行CPU指令,省去了上面的二、三、4步驟性能

CLR的JIT編譯器以及C#編譯器對本機代碼的優化
C#編譯器 :
/optimize 關閉 --> 編譯出的IL代碼會包含許多NOP指令(no-operation 空操做)和跳轉執行,vs就是利用的這些指令提供了調試的功能
/optimize 開啓 --> 優化後的代碼會更小,程序集也會相應變小,更方便閱讀IL代碼(通常估計不會有人去直接閱讀IL查找問題吧)優化

JIT編譯器:
在 /optimize 關閉 的狀況下:
  /debug - 關閉(默認) --> 有優化
  /debug (+/full/pdbonly) --> 未優化:編譯器會生成PDB文件幫助編譯器查找到局部變量並將IL代碼映射到源代碼方便調試,若是指定的是
  /debug : full 開關,編譯器還會記錄每一條IL指令生成的本機指令,但會使用額外的時間和內存
在 /optimize 開啓的狀況下:
  /debug (-/+/full/pdbonly) --> 有優化spa

圖片描述

雖然編譯器在優化代碼的過程當中會佔用額外的時間和內存,可是在實際運行階段所帶來的收益遠遠大於這些犧牲,而且性能上遠遠大於非託管代碼,例如:
  一、JIT編譯器針對不一樣的CPU優化本機代碼
  二、會根據機器對特定的判斷進行代碼優化
  三、CLR會根據運行狀態對代碼評估並從新編譯(還未實現).net

最後再來簡單瞭解一下NGen.exe工具
NGen.exe是.net framework提供的工具,它能夠將代碼提早編譯好,這樣JIT編譯器不須要在運行是編譯提高性能,但其實這個工具並非很實用
  一、由於NGen沒法對代碼進行最優的優化 --> 由於沒法肯定CPU
  二、對服務器提高不明顯 --> 由於只是在第一次運行時有幫助,後面運行的時間時相等的
  三、可能失去同步 --> 若是當前代碼與執行環境不符合,那麼就會重新用JIT編譯debug

至此關於CLR如何與程序集工做就完成了,下一節咱們將介紹.net Framework的Framework 類庫以及CTS CLS調試

相關文章
相關標籤/搜索