欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java虛擬機(jī)JVM性能優(yōu)化(二):編譯器

 更新時(shí)間:2014年09月19日 11:03:57   投稿:junjie  
這篇文章主要介紹了Java虛擬機(jī)JVM性能優(yōu)化(二):編譯器,本文先是講解了不同種類的編譯器,并對(duì)客戶端編譯,服務(wù)器端編譯器和多層編譯的運(yùn)行性能進(jìn)行了對(duì)比,然后給出了幾種常見的JVM優(yōu)化方法,需要的朋友可以參考下

本文將是JVM 性能優(yōu)化系列的第二篇文章(第一篇:傳送門),Java 編譯器將是本文討論的核心內(nèi)容。

本文中,作者(Eva Andreasson)首先介紹了不同種類的編譯器,并對(duì)客戶端編譯,服務(wù)器端編譯器和多層編譯的運(yùn)行性能進(jìn)行了對(duì)比。然后,在文章的最后介紹了幾種常見的JVM優(yōu)化方法,如死代碼消除,代碼嵌入以及循環(huán)體優(yōu)化。

Java最引以為豪的特性“平臺(tái)獨(dú)立性”正是源于Java編譯器。軟件開發(fā)人員盡其所能寫出最好的java應(yīng)用程序,緊接著后臺(tái)運(yùn)行的編譯器產(chǎn)生高效的基于目標(biāo)平臺(tái)的可執(zhí)行代碼。不同的編譯器適用于不同的應(yīng)用需求,因而也就產(chǎn)生不同的優(yōu)化結(jié)果。因此,如果你能更好的理解編譯器的工作原理、了解更多種類的編譯器,那么你就能更好的優(yōu)化你的Java程序。

本篇文章突出強(qiáng)調(diào)和解釋了各種Java虛擬機(jī)編譯器之間的不同。同時(shí),我也會(huì)探討一些及時(shí)編譯器(JIT)常用的優(yōu)化方案。

什么是編譯器?

簡單來說,編譯器就是以某種編程語言程序作為輸入,然后以另一種可執(zhí)行語言程序作為輸出。Javac是最常見的一種編譯器。它存在于所有的JDK里面。Javac 以java代碼作為輸出,將其轉(zhuǎn)換成JVM可執(zhí)行的代碼—字節(jié)碼。這些字節(jié)碼存儲(chǔ)在以.class結(jié)尾的文件中,并在java程序啟動(dòng)時(shí)裝載到j(luò)ava運(yùn)行時(shí)環(huán)境。

字節(jié)碼并不能直接被CPU讀取,它還需要被翻譯成當(dāng)前平臺(tái)所能理解的機(jī)器指令語言。JVM中還有另一個(gè)編譯器負(fù)責(zé)將字節(jié)碼翻譯成目標(biāo)平臺(tái)可執(zhí)行的指令。一些JVM編譯器需要經(jīng)過幾個(gè)等級(jí)的字節(jié)碼代碼階段。例如,一個(gè)編譯器在將字節(jié)碼翻譯成機(jī)器指令之前可能還需要經(jīng)歷幾種不同形式的中間階段。

從平臺(tái)不可知論的角度出發(fā),我們希望我們的代碼能夠盡可能的與平臺(tái)無關(guān)。

為了達(dá)到這個(gè)目的,我們?cè)谧詈笠粋€(gè)等級(jí)的翻譯—從最低的字節(jié)碼表示到真正的機(jī)器代碼—才真正將可執(zhí)行代碼與一個(gè)特定平臺(tái)的體系結(jié)構(gòu)綁定。從最高的等級(jí)來劃分,我們可以將編譯器分為靜態(tài)編譯器和動(dòng)態(tài)編譯器。 我們可以根據(jù)我們的目標(biāo)執(zhí)行環(huán)境、我們渴望的優(yōu)化結(jié)果、以及我們需要滿足的資源限制條件來選擇合適的編譯器。在上一篇文章中我們簡單的討論了一下靜態(tài)編譯器和動(dòng)態(tài)編譯器,在接下來的部分我們將更加深入的解釋它們。

靜態(tài)編譯 VS 動(dòng)態(tài)編譯

我們前面提到的javac就是一個(gè)靜態(tài)編譯的例子。對(duì)于靜態(tài)編譯器,輸入代碼被解釋一次,輸出即為程序?qū)肀粓?zhí)行的形式。除非你更新源代碼并(通過編譯器)重新編譯,否則程序的執(zhí)行結(jié)果將永遠(yuǎn)不會(huì)改變:這是因?yàn)檩斎胧且粋€(gè)靜態(tài)的輸入并且編譯器是一個(gè)靜態(tài)的編譯器。

通過靜態(tài)編譯,下面的程序:

復(fù)制代碼 代碼如下:

staticint add7(int x ){      return x+7;}

將會(huì)轉(zhuǎn)換成類似下面的字節(jié)碼:

復(fù)制代碼 代碼如下:

iload0 bipush 7 iadd ireturn

動(dòng)態(tài)編譯器動(dòng)態(tài)的將一種語言編譯成另外一種語言,所謂動(dòng)態(tài)的是指在程序運(yùn)行的時(shí)候進(jìn)行編譯—邊運(yùn)行邊編譯!動(dòng)態(tài)編譯和優(yōu)化的好處就是可以處理應(yīng)用程序加載時(shí)的一些變化。Java 運(yùn)行時(shí)常常運(yùn)行在不可預(yù)知甚至變化的環(huán)境上,因此動(dòng)態(tài)編譯非常適用于Java 運(yùn)行時(shí)。大部分的JVM 使用動(dòng)態(tài)編譯器,如JIT編譯器。值得注意的是,動(dòng)態(tài)編譯和代碼優(yōu)化需要使用一些額外的數(shù)據(jù)結(jié)構(gòu)、線程以及CPU資源。越高級(jí)的優(yōu)化器或字節(jié)碼上下文分析器,消耗越多的資源。但是這些花銷相對(duì)于顯著的性能提升來說是微不足道的。

JVM種類以及Java的平臺(tái)獨(dú)立性

所有JVM的實(shí)現(xiàn)都有一個(gè)共同的特點(diǎn)就是將字節(jié)碼編譯成機(jī)器指令。一些JVM在加載應(yīng)用程序時(shí)對(duì)代碼進(jìn)行解釋,并通過性能計(jì)數(shù)器來找出“熱”代碼;另一些JVM則通過編譯來實(shí)現(xiàn)。編譯的主要問題是集中需要大量的資源,但是它也能帶來更好的性能優(yōu)化。

如果你是一個(gè)java新手,JVM的錯(cuò)綜復(fù)雜肯定會(huì)搞得你暈頭轉(zhuǎn)向。但好消息是你并不需要將它搞得特別清楚!JVM將管理代碼的編譯和優(yōu)化,你并不需要為機(jī)器指令以及采取什么樣的方式寫代碼才能最佳的匹配程序運(yùn)行平臺(tái)的體系結(jié)構(gòu)而操心。

從java字節(jié)碼到可執(zhí)行

 一旦將你的java代碼編譯成字節(jié)碼,接下來的一步就是將字節(jié)碼指令翻譯成機(jī)器代碼。這一步可以通過解釋器來實(shí)現(xiàn),也可以通過編譯器來實(shí)現(xiàn)。

解釋

解釋是編譯字節(jié)碼最簡單的方式。解釋器以查表的形式找到每條字節(jié)碼指令對(duì)應(yīng)的硬件指令,然后將它發(fā)送給CPU執(zhí)行。

你可以將解釋器想象成查字典:每一個(gè)特定的單詞(字節(jié)碼指令),都有一個(gè)具體的翻譯(機(jī)器代碼指令)與之對(duì)應(yīng)。因?yàn)榻忉屍髅孔x一條指令就會(huì)馬上執(zhí)行該指令,所以該方式無法對(duì)一組指令集進(jìn)行優(yōu)化。同時(shí)每調(diào)用一個(gè)字節(jié)碼都要馬上對(duì)其進(jìn)行解釋,因此解釋器運(yùn)行速度是相當(dāng)慢得。解釋器以一種非常準(zhǔn)確的方式來執(zhí)行代碼,但是由于沒有對(duì)輸出的指令集進(jìn)行優(yōu)化,因此它對(duì)目標(biāo)平臺(tái)的處理器來說可能不是最優(yōu)的結(jié)果。

編譯

編譯器則是將所有將要執(zhí)行的代碼全部裝載到運(yùn)行時(shí)。這樣當(dāng)它翻譯字節(jié)碼時(shí),就可以參考全部或部分的運(yùn)行時(shí)上下文。它做出的決定都是基于對(duì)代碼圖分析的結(jié)果。如比較不同的執(zhí)行分支以及參考運(yùn)行時(shí)上下文數(shù)據(jù)。

在將字節(jié)碼序列被翻譯成機(jī)器代碼指令集后,就可以基于這個(gè)機(jī)器代碼指令集進(jìn)行優(yōu)化。優(yōu)化過的指令集存儲(chǔ)在一個(gè)叫代碼緩沖區(qū)的結(jié)構(gòu)中。當(dāng)再次執(zhí)行這些字節(jié)碼時(shí),就可以直接從這個(gè)代碼緩沖區(qū)中取得優(yōu)化過的代碼并執(zhí)行。在有些情況下編譯器并不使用優(yōu)化器來進(jìn)行代碼優(yōu)化,而是使用一種新的優(yōu)化序列—“性能計(jì)數(shù)”。

使用代碼緩存器的優(yōu)點(diǎn)是結(jié)果集指令可以被立即執(zhí)行而不再需要重新解釋或編譯!

這可以大大的降低執(zhí)行時(shí)間,尤其是對(duì)一個(gè)方法被多次調(diào)用的java應(yīng)用程序。

優(yōu)化

通過動(dòng)態(tài)編譯的引入,我們就有機(jī)會(huì)來插入性能計(jì)數(shù)器。例如,編譯器插入性能計(jì)數(shù)器,每次字節(jié)碼塊(對(duì)應(yīng)某個(gè)具體的方法)被調(diào)用時(shí)對(duì)應(yīng)的計(jì)數(shù)器就加一。編譯器通過這些計(jì)數(shù)器找到“熱塊”,從而就能確定哪些代碼塊的優(yōu)化能對(duì)應(yīng)用程序帶來最大的性能提升。運(yùn)行時(shí)性能分析數(shù)據(jù)能夠幫助編譯器在聯(lián)機(jī)狀態(tài)下得到更多的優(yōu)化決策,從而更進(jìn)一步提升代碼執(zhí)行效率。因?yàn)榈玫皆蕉嘣骄_的代碼性能分析數(shù)據(jù),我們就可以找到更多的可優(yōu)化點(diǎn)從而做出更好的優(yōu)化決定,例如:怎樣更好的序列話指令、是否用更有效率的指令集來替代原有指令集,以及是否消除冗余的操作等。

例如

考慮下面的java代碼

復(fù)制代碼 代碼如下:

staticint add7(int x ){      return x+7;}

Javac 將靜態(tài)的將它翻譯成如下字節(jié)碼:
復(fù)制代碼 代碼如下:

iload0

bipush 7

iadd

ireturn


當(dāng)該方法被調(diào)用時(shí),該字節(jié)碼將被動(dòng)態(tài)的編譯成機(jī)器指令。當(dāng)性能計(jì)數(shù)器(如果存在)達(dá)到指定的閥值時(shí),該方法就可能被優(yōu)化。優(yōu)化后的結(jié)果可能類似下面的機(jī)器指令集:
復(fù)制代碼 代碼如下:

lea rax,[rdx+7]  ret

不同的編譯器適用于不同的應(yīng)用

不同的應(yīng)用程序擁有不同的需求。企業(yè)服務(wù)器端應(yīng)用通常需要長時(shí)間運(yùn)行,所以通常希望對(duì)其進(jìn)行更多的性能優(yōu)化;而客戶端小程序可能希望更快的響應(yīng)時(shí)間和更少的資源消耗。下面讓我們一起討論三種不同的編譯器以及他們的優(yōu)缺點(diǎn)。

客戶端編譯器(Client-side compilers)

C1是一種大家熟知的優(yōu)化編譯器。當(dāng)啟動(dòng)JVM時(shí),添加-client參數(shù)即可啟動(dòng)該編譯器。通過它的名字我們即可發(fā)現(xiàn)C1是一種客戶端編譯器。它非常適用于那種系統(tǒng)可用資源很少或要求能快速啟動(dòng)的客戶端應(yīng)用程序。C1通過使用性能計(jì)數(shù)器來進(jìn)行代碼優(yōu)化。這是一種方式簡單,且對(duì)源代碼干預(yù)較少的優(yōu)化方式。

服務(wù)器端編譯器(Server-side compilers)

對(duì)于那種長時(shí)間運(yùn)行的應(yīng)用程序(例如服務(wù)器端企業(yè)級(jí)應(yīng)用程序),使用客戶端編譯器可能遠(yuǎn)遠(yuǎn)不能夠滿足需求。這時(shí)我們應(yīng)該選擇類似C2這樣的服務(wù)器端編譯器。通過在JVM啟動(dòng)行中加入 –server 即可啟動(dòng)該優(yōu)化器。因?yàn)榇蟛糠值姆?wù)器端應(yīng)用程序通常都是長時(shí)間運(yùn)行的,與那些短時(shí)間運(yùn)行、輕量級(jí)的客戶端應(yīng)用相比,通過使用C2編譯器,你將能夠收集到更多的性能優(yōu)化數(shù)據(jù)。因此你也將能夠應(yīng)用更高級(jí)的優(yōu)化技術(shù)和算法。

提示:預(yù)熱你的服務(wù)端編譯器

對(duì)于服務(wù)器端的部署,編譯器可能需要一些時(shí)間來優(yōu)化那些“熱點(diǎn)”代碼。所以服務(wù)器端的部署常常需要一個(gè)“加熱”階段。所以當(dāng)對(duì)服務(wù)器端的部署進(jìn)行性能測(cè)量時(shí),務(wù)必確保你的應(yīng)用程序已經(jīng)達(dá)到了穩(wěn)定狀態(tài)!給予編譯器充足的時(shí)間進(jìn)行編譯將會(huì)給你的應(yīng)用帶來很多好處。

服務(wù)器端編譯器相比客戶端編譯器來說能夠得到更多的性能調(diào)優(yōu)數(shù)據(jù),這樣就可以進(jìn)行更復(fù)雜的分支分析,從而找到性能更優(yōu)的優(yōu)化路徑。擁有越多的性能分析數(shù)據(jù)就能得到更優(yōu)的應(yīng)用程序分析結(jié)果。當(dāng)然,進(jìn)行大量的性能分析也就需要更多的編譯器資源。如JVM若使用C2編譯器,那么它將需要使用更多的CPU周期,更大的代碼緩存區(qū)等等。

多層編譯

多層編譯混合了客戶端編譯和服務(wù)器端編譯。Azul第一個(gè)在他的Zing JVM中實(shí)現(xiàn)了多層編譯。最近,這項(xiàng)技術(shù)已經(jīng)被Oracle Java Hotspot JVM采用(Java SE7 之后)。多層編譯綜合了客戶端和服務(wù)器端編譯器的優(yōu)點(diǎn)??蛻舳司幾g器在以下兩種情況表現(xiàn)得比較活躍:應(yīng)用啟動(dòng)時(shí);當(dāng)性能計(jì)數(shù)器達(dá)到較低級(jí)別的閾值時(shí)進(jìn)行性能優(yōu)化。客戶端編譯器也會(huì)插入性能計(jì)數(shù)器以及準(zhǔn)備指令集以備接下來的高級(jí)優(yōu)化—服務(wù)器端編譯器—使用。多層編譯是一種資源利用率很高的性能分析方式。因?yàn)樗梢栽诘陀绊懢幾g器活動(dòng)時(shí)收集數(shù)據(jù),而這些數(shù)據(jù)可以在后面更高級(jí)的優(yōu)化中繼續(xù)使用。這種方式與使用解釋性代碼分析計(jì)數(shù)器相比可以提供更多的信息。

圖1所描述的是解釋器、客戶端編譯、服務(wù)器端編譯、多層編譯的性能比較。X軸是執(zhí)行時(shí)間(時(shí)間單位),Y軸是性能(單位時(shí)間內(nèi)的操作數(shù))


圖1.編譯器性能比較

相對(duì)于純解釋性代碼,使用客戶端編譯器可以帶來5到10倍的性能提升。獲得性能提升的多少取決于編譯器的效率、可用的優(yōu)化器種類以及應(yīng)用程序的設(shè)計(jì)與目標(biāo)平臺(tái)的吻合程度。但對(duì)應(yīng)程序開發(fā)人員來講最后一條往往可以忽略。

相對(duì)于客戶端編譯器,服務(wù)器端編譯器往往能帶來30%到50%的性能提升。在大多數(shù)情況下,性能的提升往往是以資源的損耗為代價(jià)的。

多層編譯綜合了兩種編譯器的優(yōu)點(diǎn)??蛻舳司幾g有更短的啟動(dòng)時(shí)間以及可以進(jìn)行快速優(yōu)化;服務(wù)器端編譯則可以在接下來的執(zhí)行過程中進(jìn)行更高級(jí)的優(yōu)化操作。

一些常見的編譯器優(yōu)化

到目前為止,我們已經(jīng)討論了優(yōu)化代碼的意義以及怎樣、何時(shí)JVM會(huì)進(jìn)行代碼優(yōu)化。接下來我將以介紹一些編譯器實(shí)際用到的優(yōu)化方式來結(jié)束本文。JVM優(yōu)化實(shí)際發(fā)生在字節(jié)碼階段(或者更底層的語言表示階段),但是這里將使用java語言來說明這些優(yōu)化方式。我們不可能在本節(jié)覆蓋所有的JVM優(yōu)化方式;當(dāng)然啦,我希望通過這些介紹能激發(fā)你去學(xué)習(xí)數(shù)以百計(jì)的更高級(jí)的優(yōu)化方式的興趣并在編譯器技術(shù)方面有所創(chuàng)新。

死代碼消除

死代碼消除,顧名思義就是消除那些永遠(yuǎn)不會(huì)被執(zhí)行到的代碼—即“死”代碼。

如果編譯器在運(yùn)行過程中發(fā)現(xiàn)一些多余指令,它將會(huì)將這些指令從執(zhí)行指令集里面移除。例如,在列表1里面,其中一個(gè)變量在對(duì)其進(jìn)行賦值操作后永遠(yuǎn)不會(huì)被用到,所有在執(zhí)行階段可以完全地忽略該賦值語句。對(duì)應(yīng)到字節(jié)碼級(jí)別的操作即是,永遠(yuǎn)不需要將該變量值加載到寄存器中。不用加載意味著消耗更少的cpu時(shí)間,因此也就能加快代碼執(zhí)行,最終導(dǎo)致應(yīng)用程序加快—如果該加載代碼每秒被調(diào)用好多次,那優(yōu)化效果將更明顯。

列表1 用java 代碼列舉了一個(gè)對(duì)永遠(yuǎn)不會(huì)被使用的變量賦值的例子。


列表1. 死代碼

復(fù)制代碼 代碼如下:

int timeToScaleMyApp(boolean endlessOfResources){  
int reArchitect =24;  
int patchByClustering =15;  
int useZing =2;  
if(endlessOfResources)      
return reArchitect + useZing;  
else      
return useZing;
}

在字節(jié)碼階段,如果一個(gè)變量被加載但是永遠(yuǎn)不會(huì)被使用,編譯器可以檢測(cè)到并消除掉這些死代碼,如列表2所示。如果永遠(yuǎn)不執(zhí)行該加載操作則可以節(jié)約cpu時(shí)間從而改進(jìn)程序的執(zhí)行速度。

列表2. 優(yōu)化后的代碼

復(fù)制代碼 代碼如下:

int timeToScaleMyApp(boolean endlessOfResources){  
int reArchitect =24;   //unnecessary operation removed here…  
int useZing =2;  
if(endlessOfResources)      
return reArchitect + useZing;  
else      
return useZing;
}

冗余消除是一種類似移除重復(fù)指令來改進(jìn)應(yīng)用性能的優(yōu)化方式。

很多優(yōu)化嘗試著消除機(jī)器指令級(jí)別的跳轉(zhuǎn)指令(如 x86體系結(jié)構(gòu)中得JMP). 跳轉(zhuǎn)指令將改變指令指針寄存器,從而轉(zhuǎn)移程序執(zhí)行流。這種跳轉(zhuǎn)指令相對(duì)其他ASSEMBLY指令來說是一種很耗資源的命令。這就是為什么我們要減少或消除這種指令。代碼嵌入就是一種很實(shí)用、很有名的消除轉(zhuǎn)移指令的優(yōu)化方式。因?yàn)閳?zhí)行跳轉(zhuǎn)指令代價(jià)很高,所以將一些被頻繁調(diào)用的小方法嵌入到函數(shù)體內(nèi)將會(huì)帶來很多益處。列表3-5證明了內(nèi)嵌的好處。

列表3. 調(diào)用方法

復(fù)制代碼 代碼如下:

int whenToEvaluateZing(int y){   return daysLeft(y)+ daysLeft(0)+ daysLeft(y+1);}

列表4. 被調(diào)用方法
復(fù)制代碼 代碼如下:

int daysLeft(int x){   if(x ==0)      return0;   else      return x -1;}

列表5. 內(nèi)嵌方法
復(fù)制代碼 代碼如下:

int whenToEvaluateZing(int y){  
int temp =0;     
if(y ==0)
temp +=0;
else
temp += y -1;  
if(0==0)
temp +=0;
else
temp +=0-1;  
if(y+1==0)
temp +=0;
else
temp +=(y +1)-1;     
return temp;
}

在列表3-5中我們可以看到,一個(gè)小方法在另一個(gè)方法體內(nèi)被調(diào)用了三次,而我們想說明的是:將被調(diào)用方法直接內(nèi)嵌到代碼中所花費(fèi)的代價(jià)將小于執(zhí)行三次跳轉(zhuǎn)指令所花費(fèi)的代價(jià)。

內(nèi)嵌一個(gè)不常被調(diào)用的方法可能并不會(huì)帶來太大的不同,但是如果內(nèi)嵌一個(gè)所謂的“熱”方法(經(jīng)常被調(diào)用的方法)則可以帶來很多的性能提升。內(nèi)嵌后的代碼常常還可以進(jìn)行更進(jìn)一步的優(yōu)化,如列表6所示。


列表6. 代碼內(nèi)嵌后,更進(jìn)一步的優(yōu)化實(shí)現(xiàn)

復(fù)制代碼 代碼如下:

int whenToEvaluateZing(int y){   if(y ==0)return y;   elseif(y ==-1)return y -1;   elsereturn y + y -1;}

循環(huán)優(yōu)化

循環(huán)優(yōu)化在降低執(zhí)行循環(huán)體所帶來的額外消耗方面起著很重要的作用。這里的額外消耗指的是昂貴的跳轉(zhuǎn)、大量的條件檢測(cè),非優(yōu)化管道(即,一系列無實(shí)際操作、消耗額外cpu周期的指令集)。這里有很多種循環(huán)優(yōu)化,接下來列舉一些比較流行的循環(huán)優(yōu)化:

循環(huán)體合并:當(dāng)兩個(gè)相鄰的循環(huán)體執(zhí)行相同次數(shù)的循環(huán)時(shí),編譯器將試圖合并這兩個(gè)循環(huán)體。如果兩個(gè)循環(huán)體相互之間是完全獨(dú)立的,則它們還可以被同時(shí)執(zhí)行(并行)。

反演循環(huán): 最基本的,你用一個(gè)do-while循環(huán)來替代一個(gè)while循環(huán)。這個(gè)do-while循環(huán)被放置在一個(gè)if語句中。這個(gè)替換將減少兩次跳轉(zhuǎn)操作;但增加了條件判斷,因此增加了代碼量。這種優(yōu)化是以適當(dāng)?shù)脑黾淤Y源消耗換來更有效的代碼的很棒的例子—編譯器對(duì)花費(fèi)和收益進(jìn)行衡量,在運(yùn)行時(shí)動(dòng)態(tài)的做出決定。

重組循環(huán)體: 重組循環(huán)體,使整個(gè)循環(huán)體能全部的存儲(chǔ)在緩存器中。

展開循環(huán)體: 減少循環(huán)條件的檢測(cè)次數(shù)和跳轉(zhuǎn)次數(shù)。你可以把這想象成將幾次迭代“內(nèi)嵌”執(zhí)行,而不必進(jìn)行條件檢測(cè)。循環(huán)體展開也會(huì)帶來一定的風(fēng)險(xiǎn),因?yàn)樗赡芤驗(yàn)橛绊懥魉€和大量的冗余指令提取而降低性能。再一次,是否展開循環(huán)體由編譯器在運(yùn)行時(shí)決定,如果能帶來更大的性能提升則值得展開。

以上就是對(duì)編譯器在字節(jié)碼級(jí)別(或更低級(jí)別)如何改進(jìn)應(yīng)用程序在目標(biāo)平臺(tái)執(zhí)行性能的一個(gè)概述。我們所討論的都是些常見、流行的優(yōu)化方式。由于篇幅有限我們只舉了一些簡單的例子。我們的目的是希望通過上面簡單的討論來激起你深入研究優(yōu)化的興趣。

結(jié)論:反思點(diǎn)和重點(diǎn)

根據(jù)不同的目的,選擇不同的編譯器。

1.解釋器是將字節(jié)碼翻譯成機(jī)器指令的最簡單形式。它的實(shí)現(xiàn)基于一個(gè)指令查詢表。
2.編譯器可以基于性能計(jì)數(shù)器進(jìn)行優(yōu)化,但是需要消耗一些額外的資源(代碼緩存,優(yōu)化線程等)。
3.客戶端編譯器相對(duì)于解釋器可以帶來5到10倍的性能提升。
4.服務(wù)器端編譯器相對(duì)于客戶端編譯器來說可以帶來30%到50%的性能提升,但需要消耗更多的資源。
5.多層編譯則綜合了兩者的優(yōu)點(diǎn)。使用客戶端編譯來獲取更快的響應(yīng)速度,接著使用服務(wù)器端編譯器來優(yōu)化那些被頻繁調(diào)用的代碼。

這里有很多種可能的代碼優(yōu)化方式。編譯器的一個(gè)重要工作就是分析所有可能的優(yōu)化方式,然后對(duì)各種優(yōu)化方式所付出的代價(jià)與最終得到的機(jī)器指令帶來的性能提升進(jìn)行權(quán)衡。

相關(guān)文章

  • Java集合中的Set之LinkedHashSet詳解

    Java集合中的Set之LinkedHashSet詳解

    這篇文章主要介紹了Java集合中的Set之LinkedHashSet詳解,LinkedHashSet是Set集合的一個(gè)實(shí)現(xiàn),具有set集合不重復(fù)的特點(diǎn),同時(shí)具有可預(yù)測(cè)的迭代順序,也就是我們插入的順序,并且linkedHashSet是一個(gè)非線程安全的集合,需要的朋友可以參考下
    2023-09-09
  • Java編寫實(shí)現(xiàn)窗體程序顯示日歷

    Java編寫實(shí)現(xiàn)窗體程序顯示日歷

    這篇文章主要為大家詳細(xì)介紹了Java編寫實(shí)現(xiàn)窗體程序顯示日歷,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • Java語言中的文件數(shù)據(jù)流示例詳解

    Java語言中的文件數(shù)據(jù)流示例詳解

    這篇文章主要為大家介紹了Java語言中的文件數(shù)據(jù)流示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • 簡單談?wù)凧VM、JRE和JDK的區(qū)別與聯(lián)系

    簡單談?wù)凧VM、JRE和JDK的區(qū)別與聯(lián)系

    簡單的說JDK是用于開發(fā)的而JRE是用于運(yùn)行Java程序的。JDK和JRE都包含了JVM,從而使得我們可以運(yùn)行Java程序。JVM是Java編程語言的核心并且具有平臺(tái)獨(dú)立性。
    2016-05-05
  • Spring自定義注解實(shí)現(xiàn)接口版本管理

    Spring自定義注解實(shí)現(xiàn)接口版本管理

    這篇文章主要介紹了Spring自定義注解實(shí)現(xiàn)接口版本管理,RequestMappingHandlerMapping類是與 @RequestMapping相關(guān)的,它定義映射的規(guī)則,即滿足怎樣的條件則映射到那個(gè)接口上,需要的朋友可以參考下
    2023-11-11
  • MyBatis深入解讀懶加載的實(shí)現(xiàn)

    MyBatis深入解讀懶加載的實(shí)現(xiàn)

    顧名思義,懶加載就是因?yàn)橥祽辛?,懶得加載了,只有使用的時(shí)候才進(jìn)行加載。其實(shí),懶加載也加延遲加載,主要以應(yīng)用與Mybatis的關(guān)聯(lián)查詢,按照設(shè)置的延遲規(guī)則,推遲對(duì)延遲對(duì)關(guān)聯(lián)對(duì)象的select查詢
    2022-04-04
  • 關(guān)于通過Java連接mysql對(duì)反斜杠”\“轉(zhuǎn)義的測(cè)試詳解

    關(guān)于通過Java連接mysql對(duì)反斜杠”\“轉(zhuǎn)義的測(cè)試詳解

    這篇文章主要給大家介紹了關(guān)于通過Java連接mysql對(duì)反斜杠”\“轉(zhuǎn)義的測(cè)試的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家理解反斜杠”\“轉(zhuǎn)義具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。
    2017-06-06
  • 基于java實(shí)現(xiàn)畫圖板功能

    基于java實(shí)現(xiàn)畫圖板功能

    這篇文章主要為大家詳細(xì)介紹了基于java實(shí)現(xiàn)畫圖板功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • SpringCloud邁向云原生的步驟

    SpringCloud邁向云原生的步驟

    這篇文章主要介紹了SpringCloud怎么邁向云原生,通過本文我們來梳理一下Spring?Cloud的前世今生,以及未來云原生發(fā)展的趨勢(shì),可以給這些RPC框架的演進(jìn)帶來一些啟發(fā),感興趣的朋友跟隨小編一起看看吧
    2022-10-10
  • 基于Java回顧之JDBC的使用詳解

    基于Java回顧之JDBC的使用詳解

    本篇文章是對(duì)Java中JDBC的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05

最新評(píng)論