麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

Java性能優化

2019-11-18 13:22:46
字體:
來源:轉載
供稿:網友

  java語言非凡強調準確性,但可靠的行為要以性能作為代價。這一特點反映在自動收集垃圾、嚴格的運行期檢查、完整的字節碼檢查以及保守的運行期同步等等方面。對一個解釋型的虛擬機來說,由于目前有大量平臺可供挑選,所以進一步阻礙了性能的發揮。
  “先做完它,再逐步完善。幸好需要改進的地方通常不會太多。”(Steve McConnell的《About performance》[16])
  本附錄的宗旨就是指導大家尋找和優化“需要完善的那一部分”。
  
  1 基本方法
  只有正確和完整地檢測了程序后,再可著手解決性能方面的問題:
  (1) 在現實環境中檢測程序的性能。若符合要求,則目標達到。若不符合,則轉到下一步。
  (2) 尋找最致命的性能瓶頸。這也許要求一定的技巧,但所有努力都不會白費。如簡單地猜測瓶頸所在,并試圖進行優化,那么可能是白花時間。
  (3) 運用本附錄介紹的提速技術,然后返回步驟1。
  
  為使努力不至白費,瓶頸的定位是至關重要的一環。Donald Knuth[9]曾改進過一個程序,那個程序把50%的時間都花在約4%的代碼量上。在僅一個工作小時里,他修改了幾行代碼,使程序的執行速度倍增。此時,若將時間繼續投入到剩余代碼的修改上,那么只會得不償失。Knuth在編程界有一句名言:“過早的優化是一切麻煩的根源”(PRemature optimization is the root of all evil)。最明智的做法是抑制過早優化的沖動,因為那樣做可能遺漏多種有用的編程技術,造成代碼更難理解和操控,并需更大的精力進行維護。
  
  2 尋找瓶頸
  為找出最影響程序性能的瓶頸,可采取下述幾種方法:
  
  2.1 安插自己的測試代碼
  插入下述“顯式”計時代碼,對程序進行評測:
  
  long start = System.currentTimeMillis();
  // 要計時的運算代碼放在這兒
  long time = System.currentTimeMillis() - start;
  
  利用System.out.println(),讓一種不常用到的方法將累積時間打印到控制臺窗口。由于一旦出錯,編譯器會將其忽略,所以可用一個“靜態最終布爾值”(Static final boolean)打開或關閉計時,使代碼能放心留在最終發行的程序里,這樣任何時候都可以拿來應急。盡管還可以選用更復雜的評測手段,但若僅僅為了量度一個特定任務的執行時間,這無疑是最簡便的方法。
  System.currentTimeMillis()返回的時間以千分之一秒(1毫秒)為單位。然而,有些系統的時間精度低于1毫秒(如Windows PC),所以需要重復n次,再將總時間除以n,獲得準確的時間。
  
  2.2 JDK性能評測[2]
  JDK配套提供了一個內建的評測程序,能跟蹤花在每個例程上的時間,并將評測結果寫入一個文件。不幸的是,JDK評測器并不穩定。它在JDK 1.1.1中能正常工作,但在后續版本中卻非常不穩定。
  為運行評測程序,請在調用Java解釋器的未優化版本時加上-prof選項。例如:
  java_g -prof myClass
  或加上一個程序片(Applet):
  java_g -prof sun.applet.AppletViewer applet.Html
  理解評測程序的輸出信息并不輕易。事實上,在JDK 1.0中,它居然將方法名稱截短為30字符。所以可能無法區分出某些方法。然而,若您用的平臺確實能支持-prof選項,那么可試試Vladimir Bulatov的“HyperPorf”[3]或者Greg White的“ProfileViewer”來解釋一下結果。
  
  2.3 非凡工具
  假如想隨時跟上性能優化工具的潮流,最好的方法就是作一些Web站點的常客。比如由Jonathan Hardwick制作的“Tools for Optimizing Java”(Java優化工具)網站:
  http://www.cs.cmu.edu/~jch/java/tools.html
  
  2.4 性能評測的技巧
  ■由于評測時要用到系統時鐘,所以當時不要運行其他任何進程或應用程序,以免影響測試結果。
  ■如對自己的程序進行了修改,并試圖(至少在開發平臺上)改善它的性能,那么在修改前后應分別測試一下代碼的執行時間。
  ■盡量在完全一致的環境中進行每一次時間測試。
  ■假如可能,應設計一個不依靠任何用戶輸入的測試,避免用戶的不同反應導致結果出現誤差。
  
  3 提速方法
  現在,要害的性能瓶頸應已隔離出來。接下來,可對其應用兩種類型的優化:常規手段以及依靠Java語言。
  
  3.1 常規手段
  通常,一個有效的提速方法是用更現實的方式重新定義程序。例如,在《Programming Pearls》(編程拾貝)一書中[14],Bentley利用了一段小說數據描寫,它可以生成速度非常快、而且非常精簡的拼寫檢查器,從而介紹了Doug McIlroy對英語語言的表述。除此以外,與其他方法相比,更好的算法也許能帶來更大的性能提升——非凡是在數據集的尺寸越來越大的時候。欲了解這些常規手段的詳情,請參考本附錄末尾的“一般書籍”清單。
  
  3.2 依靠語言的方法
  為進行客觀的分析,最好明確把握各種運算的執行時間。這樣一來,得到的結果可獨立于當前使用的計算機——通過除以花在本地賦值上的時間,最后得到的就是“標準時間”。
  
  運算 示例 標準時間
  
  本地賦值 i=n; 1.0
  實例賦值 this.i=n; 1.2
  int增值 i++; 1.5
  byte增值 b++; 2.0
  short增值 s++; 2.0
  float增值 f++; 2.0
  double增值 d++; 2.0
  空循環 while(true) n++; 2.0
  三元表達式 (x<0) ?-x : x 2.2
  算術調用 Math.abs(x); 2.5
  數組賦值 a[0] = n; 2.7
  long增值 l++; 3.5
  方法調用 funct(); 5.9
  throw或catch異常 try{ throw e; }或catch(e){} 320
  同步方法調用 synchMehod(); 570
  新建對象 new Object(); 980
  新建數組 new int[10]; 3100
  
  通過自己的系統(如我的Pentium 200 Pro,Netscape 3及JDK 1.1.5),這些相對時間向大家揭示出:新建對象和數組會造成最沉重的開銷,同步會造成比較沉重的開銷,而一次不同步的方法調用會造成適度的開銷。參考資源[5]和[6]為大家總結了測量用程序片的Web地址,可到自己的機器上運行它們。
  
  1. 常規修改
  下面是加快Java程序要害部分執行速度的一些常規操作建議(注重對比修改前后的測試結果)。
  
  將... 修改成... 理由
  
  接口 抽象類(只需一個父時) 接口的多個繼續會妨礙性能的優化
  非本地或數組循環變量 本地循環變量 根據前表的耗時比較,一次實例整數賦值的時間是本地整數賦值時間的1.2倍,但數組賦值的時間是本地整數賦值的2.7倍
  鏈接列表(固定尺寸) 保存丟棄的鏈接項目,或將列表替換成一個循環數組(大致知道尺寸) 每新建一個對象,都相當于本地賦值980次。參考“重復利用對象”(下一節)、Van Wyk[12] p.87以及Bentley[15] p.81
  x/2(或2的任意次冪) X>>2(或2的任意次冪) 使用更快的硬件指令
  
  3.3 非凡情況
  ■字串的開銷:字串連接運算符+看似簡單,但實際需要消耗大量系統資源。編譯器可高效地連接字串,但變量字串卻要求可觀的處理器時間。例如,假設s和t是字串變量:
  System.out.println("heading" + s + "trailer" + t);
  上述語句要求新建一個StringBuffer(字串緩沖),追加自變量,然后用toString()將結果轉換回一個字串。因此,無論磁盤空間還是處理器時間,都會受到嚴重消耗。若預備追加多個字串,則可考慮直接使用一個字串緩沖——非凡是能在一個循環里重復利用它的時候。通過在每次循環里禁止新建一個字串緩沖,可節省980單位的對象創建時間(如前所述)。利用substring()以及其他字串方法,可進一步地改善性能。假如可行,字符數組的速度甚至能夠更快。也要注重由于同步的關系,所以StringTokenizer會造成較大的開銷。
  ■同步:在JDK解釋器中,調用同步方法通常會比調用不同步方法慢10倍。經JIT編譯器處理后,這一性能上的差距提升到50到100倍(注重前表總結的時間顯示出要慢97倍)。所以要盡可能避免使用同步方法——若不能避免,方法的同步也要比代碼塊的同步稍快一些。
  ■重復利用對象:要花很長的時間來新建一個對象(根據前表總結的時間,對象的新建時間是賦值時間的980倍,而新建一個小數組的時間是賦值時間的3100倍)。因此,最明智的做法是保存和更新老對象的字段,而不是創建一個新對象。例如,不要在自己的paint()方法中新建一個Font對象。相反,應將其聲明成實例對象,再初始化一次。在這以后,可在paint()里需要的時候隨時進行更新。參見Bentley編著的《編程拾貝》,p.81[15]。
  ■異常:只有在不正常的情況下,才應放棄異常處理模塊。什么才叫“不正常”呢?這通常是指程序碰到了問題,而這一般是不愿見到的,所以性能不再成為優先考慮的目標。進行優化時,將小的“try-catch”塊合并到一起。由于這些塊將代碼分割成小的、各自獨立的片斷,所以會妨礙編譯器進行優化。另一方面,若過份熱衷于刪除異常處理模塊,也可能造成代碼健壯程度的下降。
  ■散列處理:首先,Java 1.0和1.1的標準“散列表”(Hashtable)類需要造型以及非凡消耗系統資源的同步處理(570單位的賦值時間)。其次,早期的JDK庫不能自動決定最佳的表格尺寸。最后,散列函數應針對實際使用項(Key)的特征設計。考慮到所有這些原因,我們可非凡設計一個散列類,令其與特定的應用程序配合,從而改善常規散列表的性能。注重Java 1.2集合庫的散列映射(HashMap)具有更大的靈活性,而且不會自動同步。
  ■方法內嵌:只有在方法屬于final(最終)、private(專用)或static(靜

上一篇:用JAVA解壓ZIP

下一篇:抽象的進步

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 久久恋 | 成人三级视频网站 | 亚洲日色 | 91精品国产一区二区三区四区在线 | 国产一区二区视频在线播放 | 日韩黄色在线播放 | 黑人一区二区三区四区五区 | 一级毛片播放 | 精品一区二区三区欧美 | 成品片a免费直接观看 | 日韩毛片免费观看 | 久久国产一二区 | 日韩黄色免费在线观看 | 99热久草| 美女毛片在线观看 | 看免费黄色一级片 | 久久久久中文字幕 | 国产一区二区在线免费 | 国产一区二区三区手机在线 | 亚洲一级片免费观看 | 91重口视频 | 欧美18—19sex性hd | 国产喷白浆10p | 美女一级毛片 | 92精品国产自产在线 | 久草在线观看资源 | 欧美亚洲国产成人综合在线 | 国产免费观看视频 | 国产精品视频二区不卡 | 亚洲91网 | 青青草成人免费视频在线 | 毛片av网址 | 国产一级一区二区三区 | 免费一级特黄欧美大片勹久久网 | 黄色免费高清网站 | 国产三级国产精品国产普男人 | 蜜桃一本色道久久综合亚洲精品冫 | 一级做a爱片久久毛片a高清 | 成人毛片免费播放 | 一级黄色毛片a | 欧洲精品久久久 |