Practical Java(重點版)之性能

 

1. 先把焦點放到設計、數據結構和算法上。

2. 不要依賴編譯期優化技術。

編譯期優化是指:在調試階段,把編譯優化給關閉掉,當調試完畢後,再打開編譯優化讓編譯優化來選擇最便捷的代碼,這樣程序運行性能就很好。Java編譯器對產生優化後的bytecode不是很啓作用。

3. 理解運行期(runtime)代碼優化技術

4. 要使字符串拼接結合,請儘量使用StringBuffer,而不是String。

String表示建立後的對象,其字符序列不能夠再被修改了。

StringBuffer表示建立後的對象,其中的字符序列的值是可以變化的。

5. 將創建對象的成本降到最小。

創建對象所有做到事情,順序如下:

1.從heap 之中分配內存,用以存放全部的instance 變量以及這個對象連同其superclasses 的實現專屆數據(implementation-specific data)。所謂[實現專屬數據]包括指向“class and method data”的指針。

2.對象的instance 變量被初始化爲其相應的缺省值。

3.調用most derived class(最深層派生類)的構造函數(constructor)。構造函數做的第一件事就是調用superclass 的構造函數。這個程序一直反覆持續到java.1ang.object 構造函數被調用爲止。一定要記住,java.1ang.object 是一切Java 對象的base class。

4.在構造函數本體執行之前,所有instance 變量的初始值設定(initializers) 和初始化區段(initialization blocks)先獲得執行,然後才執行構造函數本體。於是base class 的構造函數最先執行,most derived class 的構造函數最後執行。這使得任何class 的構造函數都能放心大膽地使用其任何superclasses 的instance 變量。

創建對象的過程,舉例如下:

public class Light {

   private int val;

   private boolean hasData = true;

 

   public Light(int a) {

      val = a;

   }

 

   public static void main(String[] args) {

      Light lgt = new Light(2);

   }

}

Light 對象的建立步驟如下:

   1.從heap 分配內存,用來存放Light class 的instance 變量,以及一份[實現專屬數據]。

   2.此class 的instance 變量val 和hasDate,被初始化爲相應缺省值。Val 被賦值爲0,這是Int 的缺省值,hasDate 被韌始化爲缺省值fa1se。

   3.調用Light 構造函數,傳入數值5。

   4.調用Light 構造函數調用其superclass(本例爲j ava.1ang.object)的構造函數。

   5.一旦java.1ang.object 構造函數返回,Light構造函數執行其instance 變量的初值設定工作。此時將hasData 賦值爲true。

   6.將val 賦值爲5,而後Light 構造函數結束。

  7.object reference lgt 指向head 中剛剛建立完成的Light對象。

以下class特徵會增加創建對象的成本:

   1. 構造函數含有大量代碼;

   2. 內含數量衆多的對象;

  3. 繼承層次太深。

6. 慎防未用上的對象

在需要的時候才創建對象。

7.將同步化(synchronization)降至最低

   一般情況下,請不要使用synchronized,因爲會降低性能。如果不得已的話,請優先將synchronized加在函數上,然後再考慮是否加在函數內部。因爲如果你在函數本體中使用synchronized,就會產生操作代碼monitorenter 和Moniterexit 的bytecode,以及爲了處理異常而附加的代碼。

8. 儘可能使用stack變量。

9. 使用static、final 和private 函數以促成inlining(內聯)。以函數體替換掉函數調用,性能會增加。一般是小型函數被促成inlining。

10. instance 變量的初始化一次就好.對象的instance變量的默認初始化,在構造方法執行前已經執行力次,所以不需要造次執行。只有class 的static 變量和instance 變量纔有缺省值,局部變量是沒有缺省值。

11.使用原生態數據類型代碼更快更小。

  不要使用Enumeration 或Iterator 來遍歷Vector。

  Java提供了以下方式來獲取變量vector中的元素:

       a.Interaor遍歷器

       b. ListInterator遍歷器(只針對List的)

       c. Enumeration(枚舉器)

       d. Get函數

12.使用System.arraycopy來複制數組. System.arraycopy()是以本機函數(native method)實現的,因此它的執行速度更快。

13.優先使用數組,然後再考慮使用Vector和ArrayList。Vector和ArrayList底層都是以數組來實現的,而Vector調用的時候都是同步的,並且都要調用其他函數,所以在數組、Vector、ArrayList這三者中,Vector效率最慢。

14.儘可能複用對象。

15.使用緩式評估(延遲求值,lazy evaluation),是一項與語言無關的技術,它會延緩計算,直到不能再拖延爲止。工作的推遲當然不會帶來性能的提升,但如果被推遲的計算後來不再需要,從而不需執行的話,性能就提升了。也就是說免除了非必要的工作。

16. 以手工的方式將代碼優化。Javap –c 便可以反編譯.class文件。

Java –c 類(去掉了.class後綴)> test.txt(存儲文件),將會產生bytecode。

17. 編譯爲本機代碼。將java 源碼編譯爲目標平臺上的本機二進制碼(native binary code)。。這種做法並不是把java 源碼編譯爲中介的bytecode 形式.而是直接編譯爲本機機器指令(native machine instructions)。這樣做的好處在於,你不再需要爲[運行期間將bytecode 轉換爲native code 付出額外代價,因而往往獲得更快捷的代碼。缺點是通常會丟失[平臺可移植性]——儘管這或許不是你在意的。面對這個問題,至少有一種解決方案,既不會失去平臺可移植性,又享有本機二進制碼(native binary code)在執行速度上的優勢。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章