<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    精彩的人生

    好好工作,好好生活

    BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
      147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks
    有很多介紹基本的Java應(yīng)用性能調(diào)整的文章。他們都討論些簡單的技術(shù),諸如使用StringBuffer而不用String,使用synchronized關(guān)鍵字的開銷等等。
      
      這篇文章不再介紹這些東西。相反,我們關(guān)注能幫助你的基于Web的應(yīng)用更快、可升級(jí)型更好的技巧。一些技巧很詳細(xì),其他的相對(duì)簡短,但所有的都很有用。最后以一些你可提供給你的管理者的建議結(jié)束。
      
      我寫這篇文章的靈感來自于當(dāng)我的同事和我一起回憶我們的.com(dot-com)時(shí)代的時(shí)候――我們?nèi)绾卧O(shè)計(jì)能支持成千上萬的用戶和擁有緊密代碼的系統(tǒng),我們?nèi)绾螌?duì)有侵略性的致命打擊。有時(shí)在為復(fù)用設(shè)計(jì)和為性能設(shè)計(jì)之間有一個(gè)權(quán)衡。基于我的情況,性能每次都獲勝。即使你的商務(wù)顧客無需理解代碼復(fù)用,但是他們知道快速(fast-performing)的系統(tǒng)是怎么回事。讓我們開始看看我們的技巧。
      
      如何使用Exception
      Exception降低性能。一個(gè)異常拋出首先需要?jiǎng)?chuàng)建一個(gè)新的對(duì)象。Throwable接口中的構(gòu)造器調(diào)用名為fillInStackTrace()的本地方法。這個(gè)方法負(fù)責(zé)巡檢棧的整個(gè)框架來收集跟蹤信息。這樣無論何時(shí)有異常拋出,它要求虛擬機(jī)裝載調(diào)用棧,因?yàn)橐粋€(gè)新的對(duì)象在中部被創(chuàng)建。
      
      異常應(yīng)當(dāng)僅用于有錯(cuò)誤發(fā)生時(shí),而不要控制流。
      
      我有機(jī)會(huì)在一個(gè)專門用于無線內(nèi)容市場的網(wǎng)站(名字故意隱去了)看到一段代碼,其中開發(fā)者完全可以使用一個(gè)簡單的對(duì)照來查看對(duì)象是否為空。相反,他或她跳過了這個(gè)檢查而實(shí)際上拋出Null-PointerException。
      
      不要兩次初始化變量
      Java通過調(diào)用獨(dú)特的類構(gòu)造器默認(rèn)地初始化變量為一個(gè)已知的值。所有的對(duì)象被設(shè)置成null,integers (byte, short, int, long)被設(shè)置成0,float和double設(shè)置成0.0,Boolean變量設(shè)置成false。這對(duì)那些擴(kuò)展自其它類的類尤其重要,這跟使用一個(gè)新的關(guān)鍵詞創(chuàng)建一個(gè)對(duì)象時(shí)所有一連串的構(gòu)造器被自動(dòng)調(diào)用一樣。
      
      對(duì)新的關(guān)鍵詞使用優(yōu)選法則
      正如前面提到的,通過使用一個(gè)新的關(guān)鍵詞創(chuàng)建一個(gè)類的實(shí)例,在這個(gè)鏈中的所有構(gòu)造器將被調(diào)用。如果你需要?jiǎng)?chuàng)建一個(gè)類的新實(shí)例,你可以使用一個(gè)實(shí)現(xiàn)了cloneable接口的對(duì)象的clone()方法。該clone方法不調(diào)用任何類的構(gòu)造器。
      
      如果你已經(jīng)使用了設(shè)計(jì)模式作為你的體系結(jié)構(gòu)的一部分,并且使用了工廠模式創(chuàng)建對(duì)象,變化會(huì)很簡單。下面所列是工廠模式的典型實(shí)現(xiàn)。
      
      public static Account getNewAccount() {
      return new Account();
      }
      
      使用了clone方法的refactored代碼看起來可能像下面這樣:
      
      private static Account BaseAccount = new Account();
      public static Account getNewAccount() {
        return (Account) BaseAccount.clone();
      }
      
      以上的思路對(duì)實(shí)現(xiàn)數(shù)組同樣有用。
      
      如果你在應(yīng)用中沒有使用設(shè)計(jì)模式,我建議你停止讀這篇文章,趕快跑到(不要走)書店挑一本四人著的《設(shè)計(jì)模式》。
      
      在任何可能的地方讓類為Final
      標(biāo)記為final的類不能被擴(kuò)展。在《核心Java API》中有大量這個(gè)技術(shù)的例子,諸如java.lang.String。將String類標(biāo)記為final阻止了開發(fā)者創(chuàng)建他們自己實(shí)現(xiàn)的長度方法。
      
      更深入點(diǎn)說,如果類是final的,所有類的方法也是final的。Java編譯器可能會(huì)內(nèi)聯(lián)所有的方法(這依賴于編譯器的實(shí)現(xiàn))。在我的測試?yán)铮乙呀?jīng)看到性能平均增加了50%。
      
      在任何可能的地方使用局部變量
      屬于方法調(diào)用部分的自變量和聲明為此調(diào)用一部分的臨時(shí)變量存儲(chǔ)在棧中,這比較快。諸如static,實(shí)例(instance)變量和新的對(duì)象創(chuàng)建在堆中,這比較慢。局部變量的更深入優(yōu)化依賴于你正在使用的編譯器或虛擬機(jī)。
      
      使用Nonblocking I/O
      當(dāng)前的JDK版本不支持nonblocking I/O API,很多應(yīng)用試圖通過創(chuàng)建大量的線程(目光長遠(yuǎn)得用在池中)來避免阻塞。正如前述,在Java中創(chuàng)建線程有嚴(yán)重的開銷。
      
      典型的你可能看到應(yīng)用中實(shí)現(xiàn)的線程需要支持并發(fā)I/O流,像Web 服務(wù)器,并quote and auction components.
      
      JDK1.4介紹了一個(gè)nonblocking I/O包(java.nio)。如果你必須保留在較早版本的JDK,有添加了支持nonblocking I/O的第三方包。
      
      :www.cs.berkeley.edu/~mdw/proj/java-nbio/download.html.
      
      停止小聰明
      很多開發(fā)人員在腦子中編寫可復(fù)用和靈活的代碼,而有時(shí)候在他們的程序中就產(chǎn)生額外的開銷。曾經(jīng)或者另外的時(shí)候他們編寫了類似這樣的代碼:
      
      public void doSomething(File file) {
      FileInputStream fileIn = new FileInputStream(file);
      // do something
      
      他夠靈活,但是同時(shí)他們也產(chǎn)生了更多的開銷。這個(gè)主意背后做的事情是操縱一個(gè)InputStream,而不是一個(gè)文件,因此它應(yīng)該重寫如下:
      
      public void doSomething(InputStream inputStream){
      // do something
      
      乘法和除法
      我有太多的東東適用于摩爾法則――它聲明CPU功率每年成倍增長。"摩爾法則"表明每年由開發(fā)者所寫的差勁的代碼數(shù)量三倍增加,劃去了摩爾法則的任何好處。
      
      考慮下面的代碼:
      
      for (val = 0; val < 100000; val +=5) { shiftX = val * 8; myRaise = val * 2; }
      
      如果我們狡猾的利用位移(bit),性能將會(huì)六倍增加。這是重寫的代碼:
      
      for (val = 0; val < 100000; val += 5) { shiftX = val << 3; myRaise = val << 1; }
      
      代替了乘以8,我們使用同等效果的左移3位。每一個(gè)移動(dòng)相當(dāng)于乘以2,變量myRaise對(duì)此做了證明。同樣向右移位相當(dāng)于除以2,當(dāng)然這會(huì)使執(zhí)行速度加快,但可能會(huì)使你的東東以后難于理解;所以這只是個(gè)建議。
      
      選擇一個(gè)基于垃圾收集實(shí)現(xiàn)的虛擬機(jī)
      許多人可能會(huì)對(duì)Java規(guī)范不需要實(shí)現(xiàn)垃圾收集感到驚訝。設(shè)想時(shí)代已經(jīng)是我們都擁有無限內(nèi)存計(jì)算機(jī)。總之,垃圾收集器日常事務(wù)就是負(fù)責(zé)發(fā)現(xiàn)和拋出(hence garbage)不再需要的對(duì)象。垃圾收集必須發(fā)現(xiàn)那些對(duì)象不再被程序指向,并且使被對(duì)象占用的棧內(nèi)存被釋放掉。它還負(fù)責(zé)運(yùn)行任何被釋放對(duì)象的finalizer。
      
      垃圾收集故意不允許你釋放并非由你分配的內(nèi)存,從而幫助你確保程序完整,當(dāng)JVM確定CPU時(shí)間的時(shí)間表并且當(dāng)垃圾收集器運(yùn)行時(shí),這個(gè)進(jìn)程也產(chǎn)生開銷。
      
      垃圾收集器有兩個(gè)不同的步驟執(zhí)行他們的工作。
      
      實(shí)現(xiàn)了定位計(jì)算的垃圾收集器在棧中為每一個(gè)對(duì)象保留一個(gè)計(jì)數(shù)。當(dāng)一個(gè)對(duì)象被創(chuàng)建并且對(duì)它的一個(gè)定位被分配給一個(gè)變量,計(jì)數(shù)增加。當(dāng)對(duì)象越出范圍,定位計(jì)數(shù)被設(shè)置成0并且對(duì)象可以被垃圾收集。這個(gè)步驟允許參考計(jì)數(shù)器運(yùn)行在與程序執(zhí)行有關(guān)的短時(shí)間增量內(nèi)。定位計(jì)數(shù)在父子彼此擁有定位的應(yīng)用里運(yùn)行不正常。每次一個(gè)對(duì)象刷新時(shí)也會(huì)有定位計(jì)數(shù)增加和減少的開銷。
      
      實(shí)現(xiàn)了跟蹤的垃圾收集器從根節(jié)點(diǎn)開始跟蹤一列定位。對(duì)象發(fā)現(xiàn)跟蹤是否被標(biāo)記。在這個(gè)過程完成后,知道不可達(dá)的任何沒標(biāo)記的對(duì)象可以被垃圾收集。這可能以位圖(bitmap)形式實(shí)現(xiàn)或者在對(duì)象中被設(shè)置標(biāo)志。此技術(shù)參考"Mark and Sweep."(reference:定位,翻譯成“指向”好像更容易理解,是Java語言對(duì)在用對(duì)象的一個(gè)跟蹤指針。譯者著)
      
      給你的管理人員提建議
      其他方法可被用來使你的基于Web的應(yīng)用更快并且更可升級(jí)。可實(shí)現(xiàn)的最簡單的技術(shù)通常是支持cluster的策略。使用cluster,一組服務(wù)器能夠一起透明的提供服務(wù)。多數(shù)應(yīng)用服務(wù)器允許你獲得cluster支持而不需要改變你的應(yīng)用――一個(gè)大的勝利。
      
      當(dāng)然在執(zhí)行此步驟之前你可能需要考慮來自你使用的應(yīng)用服務(wù)器提供商附加的許可權(quán)利。
      
      當(dāng)看到cluster策略會(huì)有許多額外的事情考慮。經(jīng)常在體系結(jié)構(gòu)中產(chǎn)生的一個(gè)缺點(diǎn)是擁有有狀態(tài)會(huì)話。如果cluster中的一個(gè)服務(wù)器或者進(jìn)程當(dāng)?shù)簦琧luster會(huì)舍棄整個(gè)應(yīng)用。為防止此類事情發(fā)生,cluster必須給cluster中的所有成員不斷復(fù)制會(huì)話Bean的狀態(tài)。確保你也限制了存儲(chǔ)在會(huì)話中的對(duì)象的大小和數(shù)量,因?yàn)檫@些也需要被復(fù)制。
      
      Cluster也允許你分期度量你的Web站點(diǎn)的部分。如果你需要度量靜態(tài)部分,你可以添加Web服務(wù)器。如果你需要度量動(dòng)態(tài)生成的部分,你可以添加應(yīng)用服務(wù)器。
      
      在你已經(jīng)把你的系統(tǒng)放入cluster后,下一個(gè)讓你的應(yīng)用跑得更快的建議步驟是選擇一個(gè)更好的虛擬機(jī)。看看Hotspot虛擬機(jī)或者其他的飛速發(fā)展中的執(zhí)行優(yōu)化的虛擬機(jī)。隨同虛擬機(jī),看看更好的編譯器是一個(gè)更好的主意。
      
      如果你使用了幾個(gè)這兒提到的行業(yè)技術(shù)插件,并且仍然不能獲得你要的可升級(jí)性和高可用性,那么我建議一個(gè)可靠的調(diào)試策略。策略的第一步是為可能的瓶頸檢查整個(gè)體系結(jié)構(gòu)。通常,這在你的作為單線程組件或者有很多輔助連接線組件的UML流圖中很容易識(shí)別出來。
      
      最后的步驟是產(chǎn)生一個(gè)整個(gè)代碼的詳細(xì)性能估價(jià)。
      
      確保你的管理人員至少為此安排了整個(gè)項(xiàng)目時(shí)間的20%;否則不足的時(shí)間可能不止危及你整個(gè)成功的安全,還會(huì)導(dǎo)致你向系統(tǒng)引入新的缺點(diǎn)。
      
      許多組織者在適當(dāng)?shù)奈恢脹]有嚴(yán)格意義的測試基礎(chǔ)而歸咎于成本考慮也是錯(cuò)誤的。確保你的QA環(huán)境真實(shí)反映你的生產(chǎn)環(huán)境,并且你的QA測試考慮以不同的負(fù)載測試應(yīng)用,包括在最大的預(yù)期并發(fā)用戶時(shí)一個(gè)基于低負(fù)載和一個(gè)完全負(fù)載的測試。
      
      性能測試,有時(shí)測試一個(gè)系統(tǒng)的穩(wěn)定性,可能需要在每天,甚至每周的整個(gè)時(shí)期的不同關(guān)節(jié)都運(yùn)行。


    轉(zhuǎn)自:http://www.1piao.net/articles/view.asp?p=2006/2/1142260628218
    posted on 2006-04-03 11:17 hopeshared 閱讀(506) 評(píng)論(0)  編輯  收藏 所屬分類: Java
    主站蜘蛛池模板: 久久免费美女视频| 国产亚洲精品福利在线无卡一| 国产日韩在线视频免费播放| 亚洲国产精品日韩在线观看| 亚洲一区二区三区无码中文字幕| 毛色毛片免费观看| 99视频免费播放| 中文字幕不卡免费视频| 日韩亚洲翔田千里在线| 国产精品亚洲综合久久| 精品无码一区二区三区亚洲桃色| 久久久久久亚洲精品不卡| 国产精品无码免费视频二三区| 99久久国产热无码精品免费 | 免费人成视频在线| 日日麻批免费40分钟无码 | 亚洲色爱图小说专区| 又大又硬又爽免费视频| 在线免费观看毛片网站| 免费精品国产自产拍在线观看图片 | 亚洲国产精品无码观看久久| 久久亚洲国产精品成人AV秋霞| 亚洲成A人片在线观看WWW| 久久亚洲AV永久无码精品| 亚洲国产午夜福利在线播放 | 亚洲AV无码成人精品区狼人影院| 2020天堂在线亚洲精品专区| 亚洲国产精品久久网午夜 | 亚洲免费视频在线观看| 免费人成网站在线观看不卡| 中文字字幕在线高清免费电影| 一级毛片在播放免费| 一级毛片免费不卡| www.av在线免费观看| 一级做受视频免费是看美女| 中美日韩在线网免费毛片视频| 成在线人直播免费视频| 一本岛v免费不卡一二三区| 一级毛片一级毛片免费毛片| 国产人成网在线播放VA免费| 国产在线精品一区免费香蕉|