這兩天一直在準備TechEd 2006的Session,從老外的PPT裡發現,原來.NET CF 1.1中,支援兩種JIT——sJIT和iJIT,趕緊搞搞明白。沒想到google到了這樣一篇文章,學習一下搞明白了。於是草譯出來給大家分享。
原文在:http://www.danielmoth.com/Blog/2004_12_01_mothblog_archive.html。
----
現如今,所有的.NET開發人員都知道Managed 程式碼(用C#、VB.NET寫的)都是被編譯成中繼語言(IL,Intermediate Language)的,在運行時,再由即時編譯器(JIT,Just-In-Time)編譯成機器碼。這裡我們對.NET CF中的JIT引擎和案頭(.NET“完整版”)進行一個比較,並看看.NET CF 2.0中的變化。
回首往事,alpha(pre-RTM)版的CF並沒有JIT編譯器,IL都是在裝置上進行解釋的。直到RTM版本的出現(關於CF的版本請看這裡),裝置上的IL才被JIT成機器碼。這種編譯以方法為單位(和完整版一樣)。當調用一個方法時,如果沒有與這個方法對應的機器碼,則IL被編譯為機器碼並執行;下一次只要直接執行該方法的機器碼即可。這意味著JIT帶來的效能損失只會出現一次。
主要的區別在於CF將機器碼環存在GC堆裡(也就是RAM裡),並且在發生完全GC時會發生效能“顛簸(Pitching,不知道這麼翻好不好)”(有關GC的階段,請參見這裡)。換句話說,JIT產生的機器碼,會因為記憶體壓力的增大而被丟棄,因此下一次調用一個方法時,還要重新進行編譯,因此效能發生了顛簸(忽快忽慢的意思吧?)。不要把Picthing方法和實際類型的資料結構(中繼資料)搞混,中繼資料只要載入完畢後就不會“顛簸”。
要獲得你的CF應用程式的有關數字(資料),請使用效能計數器。尤其關注這幾個:Bytes Jitted、Native Bytes Jitted、Number Of Methods Jitted、Bytes Pitched和Nummber Of Methods Pitched。
另外一個區別就是.NET CF不支援ngen。因此您不能將程式集先行編譯成本機鏡像。
最後,JIT產生的程式碼大小被限制為64K(譯註:2.0裡據說取消了這個限制)。您不能超過這個限制,但大型的表單可能會導致自動產生的InitializeComponent方法的大小超出這個限制。解決的方法就是把這個方法拆分成多個比較小的方法(代價就是失去表單設計器支援)。
CF 1.0中有兩種JIT編譯器:sJIT和iJIT。前者專用於ARM裝置,後者用於其他架構的CPU(包括SH3、MIPS、x86)。sJIT在將IL編譯為機器碼時要耗費比較長的時間,但產生的程式碼比iJIT產生的快(這個PPT中有詳細的說明)。
CF 2.0使用統一的JIT,這比現有的JIT更高效,經過的最佳化更多。隨VS2005發布的模擬器使用ARM架構的CPU(而不是現有的x86架構),所以從效能的角度來看,強了許多。
如果您還記得我讀過的所有CF的書,我可以告訴您Building Solutions with the CF和CF Kick Start兩章都有一些段落是描寫JIT的。.NET CF Bible也貢獻了幾頁,用於介紹JIT代碼池/本機鏡像緩衝。
新年快樂!(沒辦法,原文04年12月31號寫的。)