日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

关于 .NET 与 JAVA 在 JIT 编译上的一些差异

發(fā)布時間:2023/12/4 asp.net 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于 .NET 与 JAVA 在 JIT 编译上的一些差异 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

最近因?yàn)楣镜囊恍┰?#xff0c;我也開始學(xué)習(xí)一些 JAVA 的知識。雖然我一直是以 .NET 語言為主的程序員,但是我并不排斥任何其它語言。在此并不討論 JAVA .NET 的好壞,僅僅是對 .NET 跟 JAVA 程序的編譯執(zhí)行過程進(jìn)行一些簡單的介紹跟比較。因?yàn)橛行﹥?nèi)容還是超出自己原來的認(rèn)知的,所以整理一下做個記錄。

.NET

.NET 程序的執(zhí)行過程大概分以下幾個步驟:

1.代碼2.語言編譯器編譯3.IL4.JIT 編譯5.運(yùn)行

.NET 平臺的程序編譯的時候是分多步的。當(dāng)我們寫好代碼開始編譯的時候需要選擇一個合適的編譯器比如csc 、vbc 。經(jīng)過這一次編譯之后我們的程序會被打包成 dll 或者 .exe 文件。這些 dll 里面其實(shí)包含的是 MSIL 。IL 做為一種中間語言,為跨平臺提供了基礎(chǔ)。當(dāng)我們把這些文件復(fù)制到目標(biāo)機(jī)器上需要真正運(yùn)行的時候,JIT (just-in-time compilation)編譯開始工作了。CLR 為我們在每個支持的平臺上都實(shí)現(xiàn)了一個 JIT 編譯器,當(dāng)一個方法在第一次運(yùn)行的時候,JIT 編譯會把 IL 編譯成目標(biāo)機(jī)器的機(jī)器碼,這樣我們的程序才能真正運(yùn)行。這也是為什么 .NET 程序第一次運(yùn)行的時候會慢一點(diǎn)的原因。解決這個問題我們可以使用工具 Ngen.exe 在第一次運(yùn)行前進(jìn)行一次預(yù)編譯,這樣就可以提升 .NET 程序的啟動速度。

分層編譯

上面大概描述了 .NET 程序編譯過程。但是 JIT 編譯可能還有一些特性需要講一下,比如分層編譯。分層編譯是從 .NET core 2.1 開始引入的一個特性。我們的 IL 到機(jī)器碼,需要 JIT 進(jìn)行一次編譯,這會影響 .NET 程序的第一次運(yùn)行的速度。微軟為了解決這個問題引入了分層編譯。分層編譯把 JIT 編譯分成兩次。當(dāng)一個方法第一次被執(zhí)行的時候,JIT 編譯器會進(jìn)行第一次快速編譯,這次編譯并不會進(jìn)行特別的優(yōu)化操作,追求的是編譯的速度。當(dāng)我們的程序運(yùn)行一段時間后,CLR 會自動感知到頻繁運(yùn)行的代碼,這些代碼被稱為熱點(diǎn)代碼。當(dāng)出現(xiàn)熱點(diǎn)代碼的時候 JIT 編譯器會重新進(jìn)行一次優(yōu)化編譯來提高熱點(diǎn)代碼的執(zhí)行效率,從而提高整個程序的性能。
通過 JIT 分層編譯, .NET 程序很好的在編譯速度跟性能之間找到了平衡。

JAVA

JAVA 程序的執(zhí)行過程大概分以下幾個步驟:

1.代碼2.語言編譯器編譯3.字節(jié)碼4.解釋/JIT編譯5.運(yùn)行

下面說說 JAVA 程序的編譯過程。
當(dāng)我們編寫好 JAVA 程序,想要執(zhí)行的時候,跟 .NET 程序一樣,同樣會選擇一個語言編譯器來進(jìn)行第一次編譯。因?yàn)?JVM 語言有好多種,比如 JAVA ,kotlin ,所以同樣會有多種語言編譯器,比如 javac,kotlinc 等等。這里還是以標(biāo)準(zhǔn)的 JAVA 為例,在語言編譯器編譯完源代碼后,會生成一堆 .class 的文件,這些文件包含的內(nèi)容被稱之為字節(jié)碼。字節(jié)碼的存在跟 MSIL 類似,同樣為跨平臺提供了一種很好的方案。只要為每個平臺實(shí)現(xiàn)接口一致的 JVM , 讓這些 JVM 來運(yùn)行字節(jié)碼就可以跨平臺了。

解釋執(zhí)行

當(dāng)我們真正要執(zhí)行 JAVA 程序的時候,這些字節(jié)碼會被 JVM 執(zhí)行。JVM 執(zhí)行的時候首先會在 CodeCache 內(nèi)查找這個方法有沒有編譯好的機(jī)器代碼,如果沒有那么交給“解釋執(zhí)行器”來解釋執(zhí)行。所謂解釋執(zhí)行,就是將代碼一行行的經(jīng)過解釋器進(jìn)行翻譯成機(jī)器碼后讓目標(biāo)機(jī)器執(zhí)行。但是這些翻譯的產(chǎn)物并不會被記錄下來,也就是說同樣的代碼每次執(zhí)行的時候都需要解釋器進(jìn)行翻譯。

JIT 編譯

顯然對于一些重復(fù)執(zhí)行的方法解釋器執(zhí)行效率會很低。為了解決這個問題,設(shè)計(jì) JVM 的工程師們想出了辦法。以 Hotspot 為例,當(dāng)程序經(jīng)過一段時間的解釋執(zhí)行后,JVM 會記錄這些方法的執(zhí)行次數(shù),當(dāng)一些方法反復(fù)被執(zhí)行的時候,JVM 會認(rèn)為這些方法是熱點(diǎn)代碼。這時候 JVM 會對這些熱點(diǎn)代碼進(jìn)行一次 JIT 編譯,這次 JIT 編譯還會根據(jù)運(yùn)行時的 profile 進(jìn)行優(yōu)化。編譯完成后把 JIT 編譯的產(chǎn)物固定下來,存儲在 CodeCache 中。這樣當(dāng)一個方法下次再次被執(zhí)行的時候 JVM 會從 CodeCache 中直接讀取機(jī)器碼來執(zhí)行。這樣熱點(diǎn)代碼的執(zhí)行效率就會大大的提供,這也是為啥有些 JAVA 程序需要進(jìn)行預(yù)熱。

總結(jié)

通過以上我們分別描述了 .NET 跟 JAVA 程序編譯執(zhí)行的過程。他們之間的區(qū)別在于 .NET 程序不管什么時候都是進(jìn)行 JIT 編譯,并且通過分層編譯技術(shù)在首次執(zhí)行速度跟性能之間找到了平衡。而 JAVA 雖然做為一門靜態(tài)語言,但是它的代碼一開始竟然是解釋執(zhí)行的(當(dāng)然這是對 Hotspot JVM而言的,有的 JVM 未必是這樣),在運(yùn)行的時候才會對熱點(diǎn)代碼進(jìn)行 JIT 編譯優(yōu)化代碼。雖然大家實(shí)現(xiàn)的方式不同,但是殊途同歸,都是通過對熱點(diǎn)代碼的二次編譯實(shí)現(xiàn)了對程序的性能的優(yōu)化。

參考

https://docs.microsoft.com/zh-cn/dotnet/standard/managed-execution-process
https://www.zhihu.com/question/37389356/answer/73820511

關(guān)注我的公眾號一起玩轉(zhuǎn)技術(shù)

總結(jié)

以上是生活随笔為你收集整理的关于 .NET 与 JAVA 在 JIT 编译上的一些差异的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。