国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

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

為JAVA性能而設計(1)

2019-11-18 12:23:15
字體:
來源:轉載
供稿:網友

  作者:eclipse
  
  為性能而設計, 第一部分: 接口事宜
  
  From java World.
  
  [b]在設計 Java 類的時候避免性能上的冒險[/b]
  
  [b][u]概要[/u][/b]
  
  許多通常的 Java 性能問題都起源于在設計過程早期中的類設計的思想, 早在許多開發者
  開始考慮性能問題之前. 在這個系列中, Brian Goetz 討論了通常的 Java 性能上的冒險
  以及怎么在設計時候避免它們.
  
  By Brian Goetz
  
  翻譯 by SuperMMX
  
  許多程序員在開發周期的后期才可是考慮性能治理. 他們經常把性能優化拖延到最后, 希
  望能完全避免 -- 有時候這種策略是成功的. 但是早期的設計思想可以影響性能優化的需
  求及其成功. 假如性能是你的程序的一個重要指標, 那么性能治理應該從第一天起就和設
  開發周期整合在一起.
  
  這個系列探索一些早期的設計思想能夠極大影響應用程序性能的方法. 在這篇文章中, 我
  專注于最通常的性能問題中的一個: 臨時變量的創建. 一個類的對象創建方式經常在設計
  時候就確定了的 -- 但不是故意的 --, 就為后來的性能問題種下了種子.
  
  閱讀整個的 "為性能而設計" 系列:
  第一部分: 接口事宜
  第二部分: 減少對象創建
  第三部分: 遠程接口 (March 23, 2001)
  
  性能問題有各種形式. 最輕易調整的是那些你簡單地為計算選擇了一個錯誤的算法 --
  就象使用使用冒泡算法來對一個大數據集進行排序, 或者在使用一個經常使用的數據項時
  不是做緩沖, 而是每次都計算. 你可以使用概要分析來簡單地找出這些瓶頸, 一旦找到了,
  你可以很輕易地改正. 但是, 許多 Java 性能問題來自一個更深的, 更難改正的源頭 --
  一個程序組件的接口設計.
  
  今天大多數程序是由內部開發的或者外部買來的組件構建而成. 甚至在程序不是很大地依
  于已經存在的組件時, 面向對象的設計過程也鼓勵應用程序包裝成組件, 這樣就簡化了設
  計, 開發和測試過程. 這些優勢是不可否認的, 你應該熟悉到這些組件實現的接口可能
  極大地影響使用它們的程序的行為和性能.
  
  在這一點上, 你可能要問什么樣的接口和性能相關. 一個類的接口不僅定義了這個類可
  以實現那些功能, 也可以定義它的對象創建行為和使用它的方法調用序列. 一個類怎樣
  定義它的構造函數和方法決定了一個對象是否可以重用, 它的方法是否要創建 -- 或者
  要求它的客戶端創建 -- 中間對象, 以及一個客戶端需要調用多少方法來使用這個類.
  這些因素都會影響程序的性能.
  
  [b][u]注重對象的創建[/u][/b]
  
  一個最基本的 Java 性能治理原則就是: 避免大量的對象創建. 這不是說你應該不創建
  任何對象而放棄面向對象的好處. 但是你必須在執行性能相關的代碼時, 在緊循環中注重
  對象的創建. 對象的創建是如此地高代價, 以至于你應該在要求性能的情況下避免不必要
  的臨時或者中間對象的創建.
  
  String 類是在那些處理文本的程序中對象創建的主要來源. 因為 String 是不可修改的,
  每當一個 String 修改或創建, 就必須創建一個新的對象. 結果就是, 關注性能的程序應
  該避免大量 String 的使用. 但是, 這通常是不可能的. 甚至當你從你的代碼中完全除去
  對 String 的依靠, 你經常會發現你自己在使用一些具有根據 String 定義的接口的組件.
  所以, 你最后不得不使用 String.
  
  [b][u]例子: 正規表達式匹配[/u][/b]
  
  作為一個例子, 假設你寫一個叫做 MailBot 的郵件服務器. MailBot 需要處理 MIME 頭格
  式 -- 象發送日期或者發送者的 email 地址 -- 在每個信息的頂部. 使用一個匹配正規
  表達式的組件來使處理 MIME 頭的過程簡單一些. MailBot 足夠聰明, 不為每個頭的行
  或者頭的元素創建一個 String 對象. 相反, 它用輸入的文本填充了一個字符緩沖區, 通
  過對緩沖區的索引來確定要處理的頭的位置. MailBot 會調用正規表達式匹配器來處理每
  個頭行, 所以匹配器的性能就非常重要. 我們以一個正規表達式匹配器類的拙劣的接
  口作為例子:
  
  public class AwfulRegEXPMatcher {
   /** Create a matcher with the given regular exPRession and which will
   Operate on the given input string */
   public AwfulRegExpMatcher(String regExp, String inputText);
   /** Retrieve the next match of the pattern against the input text,
   returning the matched text if possible or null if not */
   public String getNextMatch();
  }
  
  甚至在這個類實現了一個有效的正規表達式匹配的算法的時候, 任何大量使用它的程序
  仍然難以忍受. 既然匹配器對象和輸入的文本聯系起來, 每一次你調用它, 你必須創建
  一個新的匹配器對象. 既然你的目標是減少不必要的對象的創建, 那么使這個匹配器可以賾
  將會是一個明顯的開始.
  
  下面的類定義演示了你的匹配器的另一個可能的接口, 答應你重用這個匹配器, 但仍然
  很壞.
  
  public class BadRegExpMatcher {
   public BadRegExpMatcher(String regExp);
   /** Attempts to match the specified regular expression against the input
   text, returning the matched text if possible or null if not */
   public String match(String inputText);
   /** Get the next match against the input text, or return null if no match */
   public String getNextMatch();
  }
  
  忽略正規表達式匹配中的精細點 -- 象返回匹配的子表達式, 這個看起來無害的類定義
  會出什么問題呢? 從功能上來看, 沒有. 但是從性能的角度來看, 許多. 首先, 匹配器
  需要它的調用者創建一個 String 來代表要匹配的文本. MailBot 試圖避免創建 String
  對象, 但是當它要找到一個要做正規表達式解析的頭時, 它不得不創建一個 String 來
  滿足 BadRegExpMatcher:
  
  BadRegExpMatcher dateMatcher = new BadRegExpMatcher(...);
  while (...) {
   ...
   String headerLine = new String(myBuffer, thisHeaderStart,
   thisHeaderEnd-thisHeaderStart);
   String result = dateMatcher.match(headerLine);
   if (result == null) { ... }
  }
  
  第二, 匹配器創建了結果字符串甚至當 MailBot 只關心是否匹配了, 不需要匹配的文本時,
  這意味著要簡單使用 BadRegExpMatcher 來確認一個日期頭是否匹配一個特定的格式, 你
  必須創建兩個 String 對象 -- 匹配器的輸入和匹配的結果. 兩個對象可能看起來不多,
  但是假如你給 MailBot 處理的每個郵件的每個頭行都創建兩個對象, 這會極大地影響
  性能. 錯誤不在于 MailBot 的設計, 而在于 BadRegExpMatcher 類的設計 -- 或者使用.
  
  注重返回一個輕量型的 Match 對象 -- 可以提供 getOffset(), getLength(),
  egetMatchString() 方法 -- 而不是返回一個 String, 這不會很大提高性能. 因為創建
  一個 Match 對象可能比創建一個 String 代價要小 -- 包括產生一個 char[] 數組和
  復制數據, 你仍然創建了一個中間對象, 對你的調用者來說沒有價值.
  
  這已經足夠壞了, BadREgExpMatcher 強迫你使用它想看到的輸入形式, 而不是你可以
  提供的更有效的形式. 但是使用 BadRegExpMathcer 還有另一個危險, 潛在地給 MailBot
  的性能帶來更大的冒險: 在處理郵件頭的時候, 你開始有避免使用 String 的傾向. 但是
  既然你被迫創建許多 String 對象來滿足 BadRegExpMatcher, 你可能被引誘而放棄這個
  目標, 更加自由地使用 String. 現在, 一個組件的糟糕的設計已經影響了使用它的程序.
  甚至你后來找到了一個更好的正規表達式的組件, 不需要你提供一個 String, 那時你的
  整個程序都會受影響.
  
  [b][u]一個好一些的接口[/u][/b]
  
  你怎樣定義 BadRegExpMatcher, 而不引起這樣的問題呢? 首先, BadRegExpMatcher 應該
  不規定它的輸入. 它應該可以接受它的調用者能夠有效提供的各種輸入格式. 第二, 它
  不應該自動給匹配結果產生一個 String; 應該返回足夠的信息, 這樣調用者假如愿意的
  話可以生成它. (為方便著想, 它可以提供一個方法來做這件事, 但不是必須的) 這里
  有一個好一些的接口:
  
  class BetterRegExpMatcher {
   public BetterRegExpMatcher(...);
   /** Provide matchers for multiple formats of input -- String,
   character array, and subset of character array. Return -1 if no
   match was made; return offset of match start if a match was
   made. */
   public int match(String inputText);
   public int match(char[] inputText);
   public int match(char[] inputText, int offset, int length);
   /** Get the next match against the input text, if any */
   public int getNextMatch();
   /** If a match was made, returns the length of the match; between
   the offset and the length, the caller should be able to
   reconstrUCt the m

上一篇:為JAVA性能而設計(2)

下一篇:線程的理解

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 庄河市| 额济纳旗| 永泰县| 普陀区| 乐清市| 诸城市| 苗栗县| 土默特右旗| 钟山县| 镇江市| 池州市| 高要市| 乡宁县| 洞头县| 文成县| 鹿泉市| 营山县| 江华| 通化县| 新绛县| 兰坪| 宜昌市| 集安市| 清远市| 永宁县| 平原县| 普定县| 阿鲁科尔沁旗| 疏勒县| 马边| 日喀则市| 武强县| 扎赉特旗| 乌海市| 盱眙县| 西林县| 抚顺县| 海口市| 临安市| 磐安县| 赣榆县|