自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

優(yōu)化Java中的多態(tài)代碼 走進(jìn)新版OpenJDK

開(kāi)發(fā) 后端
Oracle的Java是一個(gè)門(mén)快速的語(yǔ)言,有時(shí)候它可以和C++一樣快。編寫(xiě)Java代碼時(shí),我們通常使用接口、繼承或者包裝類(wrapper class)來(lái)實(shí)現(xiàn)多態(tài),使軟件更加靈活。不幸的是,多態(tài)會(huì)引入更多的調(diào)用,讓Java的性能變得糟糕。部分問(wèn)題是,Java不建議使用完全的內(nèi)聯(lián)代碼,即使它是非常安全的。(這個(gè)問(wèn)題可能會(huì)在最新的Java版本里得到緩解,請(qǐng)看文章后面的更新部分)

優(yōu)化Java中的多態(tài)代碼

Oracle的Java是一個(gè)門(mén)快速的語(yǔ)言,有時(shí)候它可以和C++一樣快。編寫(xiě)Java代碼時(shí),我們通常使用接口、繼承或者包裝類(wrapper class)來(lái)實(shí)現(xiàn)多態(tài),使軟件更加靈活。不幸的是,多態(tài)會(huì)引入更多的調(diào)用,讓Java的性能變得糟糕。部分問(wèn)題是,Java不建議使用完全的內(nèi)聯(lián)代碼,即使它是非常安全的。(這個(gè)問(wèn)題可能會(huì)在***的Java版本里得到緩解,請(qǐng)看文章后面的更新部分)

考慮下這種情況,我們要用接口抽象出一個(gè)整型數(shù)組:

  1. public interface Array { 
  2.     public int get(int i); 
  3.     public void set(int i, int x); 
  4.     public int size(); 

你為什么要這樣做?可能是因?yàn)槟愕臄?shù)據(jù)是保存在數(shù)據(jù)庫(kù)里、網(wǎng)絡(luò)上、磁盤(pán)上或者在其他的數(shù)據(jù)結(jié)構(gòu)里。你想一次編碼后就不用關(guān)心數(shù)組的具體實(shí)現(xiàn)。

編寫(xiě)一個(gè)與標(biāo)準(zhǔn)Java數(shù)組一樣高效率的類并不難,不同之處在于它實(shí)現(xiàn)了這個(gè)接口:

  1. public final class NaiveArray implements Array { 
  2.     protected int[] array; 
  3.   
  4.     public NaiveArray(int cap) { 
  5.         array = new int[cap]; 
  6.     } 
  7.   
  8.     public int get(int i) { 
  9.         return array[i]; 
  10.     } 
  11.   
  12.     public void set(int i, int x) { 
  13.         array[i] = x;  
  14.     } 
  15.   
  16.     public int size() { 
  17.         return array.length; 
  18.     } 

至少在理論上,NaiveArray類不會(huì)出現(xiàn)任何的性能問(wèn)題。這個(gè)類是final的,所有的方法都很簡(jiǎn)短。

不幸的是,在一個(gè)簡(jiǎn)單的benchmark類里,當(dāng)使用NavieArray作為數(shù)組實(shí)例時(shí),你會(huì)發(fā)現(xiàn)NavieArray比標(biāo)準(zhǔn)數(shù)組慢5倍以上。就像這個(gè)例子:

  1. public int compute() { 
  2.    for(int k = 0; k < array.size(); ++k) 
  3.       array.set(k,k); 
  4.    int sum = 0
  5.    for(int k = 0; k < array.size(); ++k) 
  6.       sum += array.get(k); 
  7.    return sum; 

你可以通過(guò)使用NavieArray作為NavieArray的一個(gè)實(shí)例來(lái)稍微減緩性能問(wèn)題(避免使用多態(tài))。不幸的是,它依然會(huì)慢3倍多。而你僅是放棄了多態(tài)的好處。

那么,強(qiáng)制使用內(nèi)聯(lián)函數(shù)調(diào)用會(huì)怎樣?

一個(gè)可行的解決方法是手動(dòng)實(shí)現(xiàn)內(nèi)聯(lián)函數(shù)。你可以使用 instanceof 關(guān)鍵字來(lái)提供優(yōu)化實(shí)現(xiàn),否則你只會(huì)得到一個(gè)普通(更慢)的實(shí)現(xiàn)。例如,如果你使用下面的代碼,NavieArray就會(huì)變得和標(biāo)準(zhǔn)數(shù)組一樣快:

  1. public int compute() { 
  2.      if(array instanceof NaiveArray) { 
  3.         int[] back = ((NaiveArray) array).array; 
  4.         for(int k = 0; k < back.length; ++k) 
  5.            back[k] = k; 
  6.         int sum = 0
  7.         for(int k = 0; k < back.length; ++k) 
  8.            sum += back[k]; 
  9.         return sum; 
  10.      } 
  11.      //... 

當(dāng)然,我也會(huì)介紹一個(gè)維護(hù)問(wèn)題作為需要實(shí)現(xiàn)不止一次的同類算法…… 當(dāng)出現(xiàn)性能問(wèn)題時(shí),這是一個(gè)可接受的替代。

和往常一樣,我的benchmarking代碼可以在網(wǎng)上獲取到。

總結(jié)

  • 一些Java版本可能不完全支持頻繁的內(nèi)聯(lián)函數(shù)調(diào)用,即使它可以并且應(yīng)該支持。這會(huì)造成嚴(yán)重的性能問(wèn)題。
  • 把類聲明為 final 看起來(lái)不會(huì)緩解性能問(wèn)題。
  • 對(duì)于消耗大的函數(shù),可行的解決方法是自己手動(dòng)優(yōu)化多態(tài)和實(shí)現(xiàn)內(nèi)聯(lián)函數(shù)調(diào)用。使用 instanceof 關(guān)鍵字,你可以為一些特定的類編寫(xiě)代碼并且(因此)保留多態(tài)的靈活性。

更新

Erich Schubert使用 double 數(shù)組運(yùn)行簡(jiǎn)單的benchmark類發(fā)現(xiàn)他的運(yùn)行結(jié)果與我的結(jié)果相矛盾,而且我們的變量實(shí)現(xiàn)都是一樣的。我通過(guò)更新到***版本的OpenJDK證明了他的結(jié)果。下面的表格給出了處理10百萬(wàn)整數(shù)需要的納秒時(shí)間:

 Function  Oracle JDK 8u11  OpenJDK 1.8.0_40  OpenJDK 1.7.0_65
straight arrays 0.92 0.71 0.87
with interface 5.9 0.70 6.3
with manual inlining 0.98 0.71 0.93

正如我們看到的,***版本的OpenJDK十分智能,并且消除了多態(tài)的性能開(kāi)銷(xiāo)(1.8.0_40)。如果你足夠幸運(yùn)地在使用這個(gè)JDK,你不需要擔(dān)心這 篇文章所說(shuō)的性能問(wèn)題。但是,這個(gè)總體思想依然值得應(yīng)用在更復(fù)雜的場(chǎng)景里。例如,JDK優(yōu)化可能依然達(dá)不到你期待的性能要求。

原文鏈接: lemire 翻譯: ImportNew.com 進(jìn)林

譯文鏈接: http://www.importnew.com/14393.html

責(zé)任編輯:張偉 來(lái)源: ImportNew
相關(guān)推薦

2023-05-09 12:42:51

Java繼承多態(tài)

2009-05-14 14:46:33

SunJava 7模塊系統(tǒng)

2014-09-28 10:26:06

OpenJDK

2010-09-14 09:30:04

Java多態(tài)

2010-10-17 14:30:20

業(yè)務(wù)分析與優(yōu)化云計(jì)算物聯(lián)網(wǎng)

2023-10-27 08:49:00

JCovOpenJDK

2010-02-03 14:42:48

Fedora Open

2013-05-28 14:34:40

Java優(yōu)化代碼優(yōu)化

2009-06-17 13:26:06

scala繼承模型

2009-07-06 17:21:36

.NET中的多態(tài)

2023-11-28 18:09:49

Java多態(tài)

2011-09-13 09:56:42

Java

2023-10-20 11:24:25

JMH基準(zhǔn)測(cè)試

2018-04-08 15:40:09

Java代碼優(yōu)化

2021-06-27 06:25:14

代碼優(yōu)化技巧Java

2011-04-06 08:57:07

C++java多態(tài)

2011-07-13 09:46:23

javaScript

2022-02-16 10:47:08

代碼.Net bool函數(shù)

2009-10-14 11:14:38

ScitterScalaTwitter

2011-07-05 10:12:46

OpenJDKJava SE 7
點(diǎn)贊
收藏

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