成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

哪些因素影響Java調(diào)用的性能?

開發(fā) 后端
這得從一個(gè)小故事說起。我在一個(gè)Java核心庫的郵件列表中提交了一個(gè)修改 ——重寫了一些本是 final 的方法。一石激起千層浪,這一改動引發(fā)了幾番討論。而其中一個(gè)討論的話題是:調(diào)用一個(gè)去除 final 標(biāo)記的方法,將導(dǎo)致哪種程度的性能下降(performance regression)。

當(dāng)時(shí)發(fā)生了什么?

這得從一個(gè)小故事說起。我在一個(gè)Java核心庫的郵件列表中提交了一個(gè)修改 ——重寫了一些本是 final 的方法。一石激起千層浪,這一改動引發(fā)了幾番討論。而其中一個(gè)討論的話題是:調(diào)用一個(gè)去除 final 標(biāo)記的方法,將導(dǎo)致哪種程度的性能下降(performance regression)。

我不能確定這一改變是否會導(dǎo)致性能下降,但當(dāng)我決定將此暫時(shí)擱置一邊,試著尋找在這個(gè)討論里是否有人公布過任何相關(guān)的完整基準(zhǔn)測試(sane benchmarks)時(shí),結(jié)果空手而歸。我不能肯定地說有關(guān)的基準(zhǔn)測試是不存在的,或者說其他人沒做過這方面的探討。但我能肯定的是,在這里,連任何公 開的代碼評審都沒有。唉,看來是時(shí)候?qū)懸粋€(gè)基準(zhǔn)測試了。

基準(zhǔn)測試的方法論

我決定選用一個(gè)相當(dāng)不錯(cuò)的框架 —— JMH 來構(gòu)建基準(zhǔn)測試。如果你質(zhì)疑它測試的準(zhǔn)確性,那么建議你看下對這個(gè)框架作者(Aleksey Shipilev)的訪談,或者閱讀一下由Nitsan Wakart撰寫的一篇彰顯此框架風(fēng)采的博文

現(xiàn)在,我想知道哪些因素影響了Java方法調(diào)用的性能。所以我決定以不同方式調(diào)用方法,并測算它們的性能開銷。以單一變量為前提來構(gòu)造一套基準(zhǔn)測試,我便能逐個(gè)排除或確定,哪些因素或哪種組合會影響到方法調(diào)用的性能。

內(nèi)聯(lián)

[[138043]]

讓我們把這些方法調(diào)用點(diǎn)壓扁

方法調(diào)用的有無,是一個(gè)影響程度既是最高又是最低的因素——對于編譯器來說,徹底優(yōu)化方法調(diào)用所帶來的開銷并非不可能,有兩種方法可以實(shí)現(xiàn)這樣的需 求:直接內(nèi)聯(lián)該方法本身和使用內(nèi)聯(lián)緩存(inline cache)。千萬別被引入的這些術(shù)語給嚇倒——它們都是通俗易懂的。現(xiàn)在我們假設(shè)有一個(gè)叫Foo的類,該類定義了一個(gè)叫bar的方法:

class Foo {
  void bar() { ... }
}

我們以如下的方式調(diào)用bar方法:

Foo foo = new Foo();
foo.bar();

這里有一個(gè)重要的知識點(diǎn):實(shí)際調(diào)用 bar 的位置,即 foo.bar(),稱為調(diào)用點(diǎn)(callsite)。 當(dāng)我們說一個(gè)方法“被內(nèi)聯(lián)”,意指方法體被插入到了調(diào)用點(diǎn)的位置上,以代替方法調(diào)用。對于那些由許多短小的方法所構(gòu)成的程序——我稱之為被適當(dāng)分解的程序 ——內(nèi)聯(lián)可以有效地提升性能。這是因?yàn)榻Y(jié)束以后可以發(fā)現(xiàn),程序并沒有把所有時(shí)間用在方法調(diào)用上,實(shí)際上程序并沒有工作!我們在JMH中可以借由 CompilerControl 注釋控制一個(gè)方法是否被內(nèi)聯(lián)。關(guān)于內(nèi)聯(lián)緩存的概念,我稍后再來說明。

層次結(jié)構(gòu)深度與重寫子類方法

[[138044]]

是因?yàn)楦改缸尯⒆勇聛砹藛幔?/strong>

如果我們移除一個(gè)方法的 final 關(guān)鍵字,便意味著我們能夠重寫它。所以這是另一個(gè)在進(jìn)行測試我們需要考慮的情況。我會選擇在同一層次結(jié)構(gòu)中不同層次的子類里調(diào)用一些方法,并且在這些方法里有一些是會被不同層次的子類重寫的。這樣的測試能讓我們確定或排除深的層次結(jié)構(gòu)是否影響到重寫所帶來的性能開銷。

多態(tài)性

[[138045]]

動物世界:多態(tài)是如何表現(xiàn)的

先前我提到調(diào)用點(diǎn)這一概念時(shí),我偷偷地回避了一個(gè)相當(dāng)重要的問題——因?yàn)樵谧宇愔锌梢灾貙懸粋€(gè)非 final 方法,這使得調(diào)用點(diǎn)可以調(diào)用不同的方法。現(xiàn)假設(shè)我傳入一個(gè) Foo 的實(shí)例或一個(gè)重寫了 bar 子類—— Baz的實(shí)例,編譯器如何得知要調(diào)用哪一個(gè) bar 方 法呢?在默認(rèn)情況下,方法將在Java中被虛擬化(可重寫)。對于任一調(diào)用點(diǎn),編譯器需要在一個(gè)稱為虛擬表(vtable)的表中尋找與其對應(yīng)的方法。這 是個(gè)非常耗時(shí)的過程,所以,能進(jìn)行優(yōu)化的編譯器,總是會試圖減少這種查詢帶來的開銷。一種方法就是先前提到的內(nèi)聯(lián),這的確是個(gè)良策,但前提是編譯器能證明 在給定的調(diào)用點(diǎn)上調(diào)用的方法唯一。而這樣的調(diào)用點(diǎn)我們稱為單態(tài)(monomorphic)調(diào)用點(diǎn)。

不幸的是,進(jìn)行這種分析需要耗費(fèi)大量時(shí)間。所以在實(shí)際過程中,確定一個(gè)調(diào)用點(diǎn)是否單態(tài)是個(gè)不太可取的方法。對此,JIT編譯器傾向于使用一種替代方 法:列出哪些類可以在此調(diào)用點(diǎn)被調(diào)用,接著根據(jù)之前的N個(gè)相同的調(diào)用猜測此調(diào)用點(diǎn)是否是單態(tài)的。以假定某個(gè)調(diào)用點(diǎn)永遠(yuǎn)為單態(tài),來進(jìn)行投機(jī)性質(zhì)的優(yōu)化往往是 可取的行為。因?yàn)檫@樣的優(yōu)化往往都是正確的,但也因它無法確保永遠(yuǎn)正確,編譯器需要在方法調(diào)用之前注入一個(gè)用于檢查方法類型的防護(hù)機(jī)制。

除了單態(tài)的調(diào)用點(diǎn)以外,還有兩種調(diào)用點(diǎn)我們希望對其進(jìn)行優(yōu)化。一種稱為雙態(tài)(bimorphic) 調(diào)用點(diǎn),在該點(diǎn)上有兩個(gè)候選方法。對此你依然可以實(shí)現(xiàn)內(nèi)聯(lián)——借助防護(hù)代碼,讓其檢測應(yīng)調(diào)用哪一個(gè)方法,并引導(dǎo)程序跳轉(zhuǎn)至內(nèi)聯(lián)在調(diào)用點(diǎn)的兩個(gè)方法體中真正 對應(yīng)的那一個(gè)。這樣的方式還是比查看所有虛擬表的方式要快得多。但在某些情況下,我們得利用內(nèi)聯(lián)緩存來進(jìn)行優(yōu)化。內(nèi)聯(lián)緩存需要借助一張?zhí)囟ǖ奶D(zhuǎn)表 ( jump table),這種表類似于對虛擬表查找做的一份緩存。hotsopt JIT編譯器支持雙態(tài)內(nèi)聯(lián)緩存,并定義那些擁有三個(gè)及三個(gè)以上候選方法的調(diào)用點(diǎn)為超多狀態(tài)(megamorphic)調(diào)用點(diǎn)。

這就使得我在基準(zhǔn)測試與探究當(dāng)中,需要額外地把調(diào)用情況劃分為三類:單態(tài)、雙態(tài)、超多狀態(tài)。

結(jié)果

讓我們把結(jié)果分類組織,以便研究細(xì)節(jié)。我已經(jīng)提供了統(tǒng)計(jì)產(chǎn)生的原始數(shù)據(jù)。但我們的興 趣點(diǎn)不應(yīng)放在性能測試結(jié)果的具體數(shù)值上,而應(yīng)是不同類型的方法調(diào)用的性能開銷之間的比率以及各自的錯(cuò)誤率是否夠低。如果最快與最慢的結(jié)果之間比率為 6.26,則說明這是一個(gè)顯著性差異。由于測試時(shí)使用的是空方法(詳見源代碼),所以在實(shí)際應(yīng)用中,這樣的差異會更大。

你可以在 github上查看此次基準(zhǔn)測試的源代碼。為了避免產(chǎn)生困惑,待會所有的結(jié)果將分塊顯示。最后顯示的多態(tài)的基準(zhǔn)測試是在 PolymorphicBenchmark 類中進(jìn)行,其它的則在 JavaFinalBenchmark 類中。

簡單調(diào)用點(diǎn)

哪些因素影響Java調(diào)用的性能?

最先看到的的一組結(jié)果,是比較調(diào)用一個(gè) virtual 方法、一個(gè) final 方法和一個(gè)擁有很深的層級結(jié)構(gòu),同時(shí)被所有子類重寫的方法所帶來的開銷。注意,調(diào)用這些方法的時(shí)候我們都強(qiáng)制編譯器不要內(nèi)聯(lián)它們。我們可以看到:三者在時(shí)間花費(fèi)上相差甚微,并且各自的誤差率都小到可以忽略。對此我們可以斷定,僅添加一個(gè) final 關(guān)鍵字并不會大幅度提升調(diào)用性能,重寫一個(gè)方法也不見得會帶來什么影響。

內(nèi)聯(lián)簡單調(diào)用

哪些因素影響Java調(diào)用的性能?

現(xiàn)在,我們在開啟內(nèi)聯(lián)的情況下再來一次相同的測試。由結(jié)果可見,final 方 法和 virtual 方法的時(shí)間花費(fèi)依舊相近,并比在沒有內(nèi)聯(lián)的情況下快了4倍,我將此歸功于內(nèi)聯(lián)優(yōu)化。相比而言,被所有子類重寫的方法的結(jié)果可就沒那么好看了。我推測這是由 于此方法有多個(gè)子類實(shí)現(xiàn),使得編譯器必須插入一個(gè)類型保護(hù)。有關(guān)的細(xì)節(jié)我們將在研究多態(tài)性的結(jié)果時(shí)進(jìn)行闡述。

類層次結(jié)構(gòu)的影響

哪些因素影響Java調(diào)用的性能?

哇噢——這兒有好幾個(gè)的方法!方法名稱的編號(1~4)代表該方法調(diào)用的層次。因此,parentMethod4 表示我們調(diào)用的方法位于class的上面第四級。(譯注:在源代碼中該方法位于頂層的父類)。由此結(jié)果我們能斷定,結(jié)構(gòu)層次的深度對性能開銷沒有影響。在開啟內(nèi)聯(lián)的實(shí)例中,結(jié)論也是一樣。這個(gè)測試中,被內(nèi)聯(lián)的方法的性能與 inlinableAlwaysOverriddenMethod 相當(dāng),但稍遜于 inlinableVirtualInvoke。我依舊認(rèn)為這與使用了類型保護(hù)有關(guān)。事實(shí)上JIT編譯器能剖析所有候選方法,從而只內(nèi)聯(lián)對應(yīng)的那一個(gè),但這并不證明它總會這么干。

類的層級結(jié)構(gòu)對final方法的影響

哪些因素影響Java調(diào)用的性能?

該測試的結(jié)論與第一個(gè)測試一樣 —— final 關(guān)鍵字不會產(chǎn)生任何影響。我本以為該測試將證明 inlinableParentFinalMethod4 以無類型保護(hù)的方式進(jìn)行內(nèi)聯(lián),但結(jié)果表明事實(shí)并非如此。

多態(tài)性

哪些因素影響Java調(diào)用的性能?

最后,我們來看涉及多態(tài)分派(polymorphic dispatch)的測試結(jié)果。單態(tài)調(diào)用的性能開銷與之前virtual方法相近。但對于雙態(tài)與超多狀態(tài)調(diào)用,由于需要在一張較大的虛擬表上面進(jìn)行查找, 所以需要更多的時(shí)間。而一旦我們開啟內(nèi)聯(lián)支持,類型分析(type profiling )將會在單態(tài)或雙態(tài)的調(diào)用點(diǎn)啟用,使得在這些調(diào)用點(diǎn)上的方法調(diào)用的開銷減少。但與層級結(jié)構(gòu)的實(shí)例一樣,這只會減少少量的時(shí)間。相比而言,超多狀態(tài)的實(shí)例則 依舊耗時(shí)較長。記住,我并沒有說在這個(gè)測試中hotspot禁用了內(nèi)聯(lián),它只是沒有實(shí)現(xiàn)多態(tài)調(diào)用點(diǎn)的多態(tài)內(nèi)聯(lián)緩存。

我們從中學(xué)到了什么?

我認(rèn)為,需要我們引起注意的是,很多人沒有認(rèn)識到不同方式的方法調(diào)用所花費(fèi)的時(shí)間是不一樣的。即便有些人發(fā)現(xiàn)了這種問題,但他們不去證明是否真的如此。作為第一個(gè)吃螃蟹的人,我列出了各種壞的假設(shè),因此我希望這份研究能夠幫助到大家。以下是我很樂于與大家分享的一些結(jié)論:

  • 最快與最短的方法調(diào)用的類型之間存在巨大的性能差別。

  • 在實(shí)際應(yīng)用中,添加或刪除final關(guān)鍵字并不會真正影響性能。但如果除此以外,你還在層級結(jié)構(gòu)上進(jìn)行某些操作,那這些行為則可能導(dǎo)致性能下降。

  • 更深的類的層次結(jié)構(gòu)并不會真正影響到調(diào)用的性能。

  • 單態(tài)調(diào)用比雙態(tài)調(diào)用更快。

  • 雙態(tài)調(diào)用比超多狀態(tài)調(diào)用更快。

  • 我們在能夠進(jìn)行剖析(profile-ably),但是不能進(jìn)行查驗(yàn)的單態(tài)調(diào)用點(diǎn)中看到類型保護(hù),這種保護(hù)會使得這些調(diào)用點(diǎn)的調(diào)用性能低于那些能夠進(jìn)行查驗(yàn)的單態(tài)調(diào)用點(diǎn)。

我想說的是,對我而言,類型保護(hù)帶來的性能開銷是一個(gè)“重大發(fā)現(xiàn)”。這是一個(gè)我之前很少提及,并且總是當(dāng)做無關(guān)事物忽視掉的因素。

注意事項(xiàng)與進(jìn)一步工作

本文不能囊括這個(gè)話題的全部內(nèi)容。因?yàn)椋?/p>

  • 這篇博文所關(guān)注的影響到方法調(diào)用的性能的因素,只與類型有關(guān)。所以,有一個(gè)因素我并未提及:方法的長短或者說調(diào)用棧的深度——如果方法太長,那么它將不會被內(nèi)聯(lián),為此你必須承受方法調(diào)用所帶來的開銷。另外,為了使代碼具有易讀性,你也應(yīng)當(dāng)把方法寫得短小一些。

  • 在本次測試的所有我并沒有嘗試引入接口。如果你對此有興趣的話,這里有一篇有關(guān)接口調(diào)用的性能的研究Mechanical Sympathy

  • 還有一個(gè)因素被我完全忽視了,那就是方法內(nèi)聯(lián)的優(yōu)化方式在不同編譯器上的效果差異。當(dāng)編譯器是僅關(guān)注某個(gè)方法(內(nèi)部過程優(yōu)化)時(shí),它們需要足夠地信息才能有效優(yōu)化。內(nèi)聯(lián)的限制可以有效地減少其它優(yōu)化所需要關(guān)注的范圍。

  • 試著站在匯編語言的層面進(jìn)行解釋的話,會涉及更多的細(xì)節(jié)內(nèi)容。

或許以上內(nèi)容已經(jīng)超出了本文的范疇,需要另寫博文進(jìn)行討論。

 
責(zé)任編輯:王雪燕 來源: ImportNew
相關(guān)推薦

2011-07-01 14:25:20

網(wǎng)站收錄

2018-02-07 08:13:32

機(jī)房屏蔽材料布線

2024-11-27 15:17:07

2021-05-18 07:46:06

存儲系統(tǒng)IOPS

2013-10-12 10:04:17

2011-11-01 11:02:20

云計(jì)算云服務(wù)

2022-04-24 11:49:01

物聯(lián)網(wǎng)安全制造業(yè)

2011-05-13 13:07:46

數(shù)據(jù)備份速度

2013-12-17 10:13:19

2023-03-30 16:18:00

智能PDU數(shù)據(jù)中心

2018-08-27 10:10:03

2021-04-23 22:37:45

網(wǎng)絡(luò)安全軟件系統(tǒng)

2021-08-16 21:11:31

人臉識別AI人工智能

2021-09-27 09:48:37

UPS蓄電池電源

2015-05-18 16:53:56

OCZ

2011-12-29 09:47:02

數(shù)據(jù)中心外包服務(wù)商

2012-12-10 13:24:15

回歸分析數(shù)據(jù)挖掘

2019-07-19 14:51:54

2017-09-01 15:05:23

網(wǎng)站性能互聯(lián)網(wǎng)DNS

2015-07-16 10:34:04

網(wǎng)絡(luò)設(shè)備服務(wù)器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 欧美精品导航 | 超碰97av| 黄色一级大片在线免费看产 | 欧一区| 久久噜噜噜精品国产亚洲综合 | 国产精品揄拍一区二区 | 亚洲精品国产a久久久久久 午夜影院网站 | 色爱综合网 | 国产高清在线观看 | 一区二区在线免费播放 | 亚洲一区二区三 | 欧美影院 | 1000部精品久久久久久久久 | 国产精品欧美一区二区三区不卡 | 日韩中文字幕免费 | 伊人春色成人网 | 国产精品不卡视频 | 久久精品成人 | 九九热精品在线视频 | 久久在看 | 国产激情视频在线观看 | 狠狠av| 久久人人爽人人爽人人片av免费 | av大片| 久久这里只有精品首页 | 日本视频中文字幕 | 欧美视频在线看 | 天堂av影院 | 狠狠艹| 国产一区二区三区在线 | 日韩精品一区在线 | 国产精品69久久久久水密桃 | 国产三区在线观看视频 | 国产亚洲一区二区三区 | 欧美一区二区在线免费观看 | 色综合99| 伊人影院在线观看 | 一本色道精品久久一区二区三区 | 日韩免费一区 | 99久久成人 | 偷拍自拍网 |