實踐28
将精力集中于建立良好可靠的設計(必要時易于修改)
高效代碼與 1 良好的設計 2 明智地選擇資料結構 3 明智地選擇算法 三者的密切程度,遠大于與實作語言的關系。
實踐29
常見的Java編譯器幾乎做不了什麼優化工作,是以不要依賴編譯器的優化功能(特别Java的)
我們有三個選擇:1 手動優化 2 使用第三方優化編譯器 3 依靠諸如JIT,Hotspot這樣的運作期優化政策
實踐30
了解運作期代碼優化技術
JIT的目的在于将bytecode于運作期轉換為本機二進制碼(native binary code)。
必須確定用于[收集資料和執行優化]的時間,不能超過優化所節省的時間。并且JIT自身啟動也需要實踐。
許多嵌入式系統或許并沒有足夠的記憶體用于JIT或Hotspot執行層。
實踐31
如果要執行字元串連接配接,StringBuffer優于String
實踐32
将待建對象的數量和體積減至最小
對象構件過程中發生的順序:
1 從heap中配置設定記憶體,用于存放全部的instantce變量及這個對象連同其superclass的專有資料(域和方法指針)
2 對象的instance變量初始化對應預設值
3 調用最深層派生類的構造函數,一直到Object
4 在構造函數本體執行前 所有instance變量初始值設定式和初始化區段先執行,再執行本體。
如果确定性能問題是由重型對象的建立造成:
1 使用緩式評估(延遲求值,lazy evaluation)
2 重新設計class
3 将class分解為多個輕型對象,使最關鍵的部分隻使用輕型對象
增加對象建立成本的特征
1 構造函數中有大量代碼
2 内含數量衆多和龐大的對象 它們的初始化将是構造函數的一部分
3 太深的繼承層次
實踐33
隻有在需要的時候再建立對象
實踐34
隻有在必要的時候 才使用synchronized 并且如果整個函數需要被同步化,為了産生體積較小且執行更快的代碼,應優先使用函數修飾符,而不是在函數内使用同步塊
實踐35
盡可能使用stack變量
stack變量為JVM提供了更高效的bytecode指令序列,是以在循環内重複通路static變量或instance變量時,應當将它們暫時存儲于stack變量中,以便獲得更快的運作速度。
實踐36
以方法體替換方法調用,會導緻更快速的程式,如果要令函數為inline,必須先聲明它們為static、final或private。
實踐37
所有static變量和instance變量都會自動獲得預設值,是以不必重新将它們設為預設值。随意最好的class應該是這樣的:
class A{
private int count;
private boolean flag;
private Point pt;
public A(){
pt=new Point(0,0);
}
}
這裡既不需要在開始對count,flag初始化,也不用在構造函數内初始化
實踐38
使用基本類型,這将比使用包裝類産生更小更快的代碼
實踐39
作周遊時,使用get()函數而不是Enumeration或Iterator/LisIterator,這樣會導緻更少的函數調用,也就意味着更快的運作速度
實踐40
使用System.arraycopy()來複制arrays。因為這個是本機(native)函數,速度更快。
注意copy的2個原數組和目标數組必須同類型且長度相同
實踐41
優先使用array,再考慮ArrayList和Vector
Vector最慢 因為他是同步的 ArrayList是不帶同步的
實踐42
盡可能的複用現有的對象 但是要注意如果對象是objectreference 可能會引起不希望的結果
實踐43
采用延遲求值 lazy evaluation, 延緩那些可能永遠也不需要進行的工作
實踐44
手工優化代碼
剔除空白函數
剔除無用代碼
削減強度(例如用+=)
合并常量
删減相同的子表達式
展開循環(會産生更多的代碼)
簡化代數
搬移循環内的不變式
實踐45
編譯為本機代碼,通常可以獲得運作速度更快的代碼,但卻是以必須在各種不同的本機方案中取舍。