前言java
性能優化自己是一個很大的主題,涵蓋程序的方方面面,任何不慎的操做,都有可能對性能形成比較大的影響,要知道程序的性能是能夠累加的,多處的性能低下,會影響總體的性能,其後果可能也是多方面的,本文總結了目前工做中,所須要知道的大部分性能優化點,一部分我的總結,一部分來自於互聯網。但總體上,都是提綱性的,並無列出具體的實例,由於寫這方面主題的達人實在太多了,因此,我得站在巨人的肩膀上,具體細節,請參考對應的連接。算法
性能低下的現象
數據庫
遊戲:界面很卡,FPS低編程
搜索性能差數組
服務器響應速度慢緩存
OS:界面無響應性能優化
性能低下的後果:下降用戶體驗服務器
用戶流失網絡
項目失敗數據結構
引起災難
…
容易引起性能問題的點
硬件
IO操做
數據庫
網絡
函數調用
數據結構
程序邏輯
….
從全局考慮
硬件性能
架構設計
核心數據結構
……
從微觀考慮
小規模修改程序,提升性能:程序的性能是能夠累加的
簡單代碼設計
類和函數設計:合適的數據類型和算法
用快速排序代替冒泡排序
用二分查找代替線性查找
業務邏輯的實現
……
一些觀點
高效代碼≠更好代碼≠高質量代碼(易修改,易擴充,易維護)
80/20法則:4%的代碼佔用了50%以上的運行時間
隨時隨地進行優化 ==>將陷入無休止的優化泥潭
開發階段前期:功能都未實現,何談優化,但在設計的時候,須要考慮到對應風險。
開發階段中後期:功能部分完善,經過現象進行模塊優化
開發階段後期:功能完善,充分考慮總體性,經過現象進行系統優化
後期優化沒法知足性能要求----架構先天不足,只能大批量重構
過度提升性能會損害程序的可讀性和可維護性
優先實現功能,而後再進行優化
程序功能的正確性比性能更重要
真正高性能的程序設計:
more small, more fast
more simple, more fast
……
方法論
在進行性能優化前,確保該功能是否已基本完整。
Key Points
是否考慮經過修改需求來提升性能?
是否考慮經過修改總體設計提升性能?
是否考慮經過來修改類的設計提升性能?
在開始修改前,程序是徹底正確的麼?
是否在修改前是否進行性能評估?
是否記錄了每次修改後的性能的變化?
若是沒有帶來預期的性能提升,是否徹底放棄所作的代碼調整?
是否對每一個性能瓶頸進行不止一次的嘗試?
是否反覆進行代碼調整,直到最優?
……
性能瓶頸的發現
找出瓶頸,集中火力對付佔用絕大部分資源的少許代碼。
途徑:
Code Review
經過最基本優化策略優化代碼
代碼性能測量
1) 經過性能Log記錄函數調用時間,找出瓶頸點
LogUtil.d(TAGConstant.TAG_PERFORMANCE,"Load media info into group begin......");
longstart = System.currentTimeMillis();
……
LogUtil.d(TAGConstant.TAG_PERFORMANCE,「Load media info into group end, Total Time: 」 + (System.currentTimeMillis() -start) + 「 ms」);
2) 使用性能分析工具:
Traceview(參考:Android性能調優工具TraceView介紹)
Monkey
monkeyrunner
注:後兩個我我的沒有使用過,不作介紹,優先推薦使用TraceView工具
如何優化
優化自己是一個很大的主題,我這是主要是針對於Android平臺來講的。我的認爲,優化能夠分紅好幾部分:
一是JAVA語法層次通用的優化,如儘可能使用局部變量(棧變量),IO緩衝等。
二是通用的Android性能優化,如同步改異步,各類緩存的使用等
三是應用程序內部的性能優化,如內部邏輯、數據插入及查找、數據結構的安排與組織等
如下部分針對於上述3種類型,分別進行簡要說明:
基本優化策略:JAVA語法層次的優化
(如下部分來自於:http://blog.csdn.net/aomandeshangxiao/article/details/8115612#t1,具體作法請參考該鏈接)
類和對象使用技巧
儘可能少用new生成新對象
使用clone方法生成新對象
儘可能使用局部變量棧變量
減小方法調用
使用final類和final/static/private方法
讓訪問實例內變量的 getter/setter 方法變成final
避免不須要的 instanceof 操做
避免不須要的造型操做
儘可能重用對象
不要重複初始化變量
不要過度建立對象
Java IO技巧
使用緩衝提升IO性能
lnputStream比Reader高效,OutputStream比Writer高效
在適當的時候用byte替代char
有緩衝的塊操做IO要比緩衝的流字符IO快
序列化時使用原子類型
在finally塊中關閉stream
SQL語句
儘早釋放資源
異常Exceptions使用技巧
避免使用異常來控制程序流程
儘量重用異常
將trycatch 塊移出循環
線程使用技巧
在使用大量線程Threading的場合使用線程池管理
防止過多的同步
同步方法而不要同步整個代碼段
在追求速度的場合用ArrayList和HashMap代替Vector和Hashtable
使用notify而不是notifyAll
不要在循環中調用 synchronized同步方法
單線程應儘可能使用 HashMap,ArrayList
其它經常使用技巧
使用移位操做替代乘除法操做能夠極大地提升性能
對Vector中最後位置的添加刪除操做要遠遠快於塒第一個元素的添加刪除操做
當複製數組時使用System.arraycop方法
使用複合賦值運算符
用int而不用其它基本類型
在進行數據庫鏈接和網絡鏈接時使用鏈接池
用壓縮加快網絡傳輸速度一種經常使用方法是把相關文件打包到一個jar文件中
在數據庫應用程序中使用批處理功能
消除循環體中沒必要要的代碼
爲vectors 和 hashtables定義初始大小
若是隻是查找單個字符的話用charat代替startswith
在字符串相加的時候使用 charat()代替startswith() 若是該字符串只有一個字符的話
對於 boolean 值避免沒必要要的等式判斷
對於常量字符串用string 代替 stringbuffer
用stringtokenizer 代替 indexof 和substring
使用條件操做符替代if cond else 結構
不要在循環體中實例化變量
肯定 stringbuffer的容量
不要老是使用取反操做符
與一個接口 進行instanceof 操做
採用在須要的時候纔開始建立的策略
經過 StringBuffer 的構造函數來設定他的初始化容量能夠明顯提高性能
合理使用 javautilVector
不要將數組聲明爲public static final
HaspMap 的遍歷
array數組和 ArrayList 的使用
StringBufferStringBuilder 的區別
儘可能使用基本數據類型代替對象
用簡單的數值計算代替複雜的函數計算好比查表方式解決三角函數問題
使用具體類比使用接口效率高但結構彈性下降了但現代 IDE均可以解決這個問題
考慮使用靜態方法
應儘量避免使用內在的GET/SET 方法
避免枚舉浮點數的使用
二維數組比一維數組佔用更多的內存空間大概是 10倍計算
SQLite
奇偶判斷
實際上,Android自己的Training文檔也提供給咱們不少可參考的內容,如下僅枚舉一些KeyPoint,固然,有的內容是與上面的策略是重複的。
原文參考:Performance Tips
譯文參考:Android應用開發者指南:性能優化(1)
其它參考:Android開發性能優化簡介
整體上來講,想要寫出高效代碼,咱們要遵循兩條基本的原則:
不做沒有必要的工做。
儘可能避免內存分配。
Key Point:
避免建立沒必要要的對象
用靜態代替虛擬
避免內部的Getters/Setters
對常量使用Static Final修飾符
使用改進的For循環語法(for-each)
在有內部類的狀況考慮使用包權限來替代私有訪問
避免使用浮點數
瞭解並使用類庫
合理利用Native方法
通用Android性能優化
佈局優化
(原文參考:ImprovingLayout Performance)
儘可能減小Android程序佈局中View的層次,View層次越多,效率就越低
使用<include/>複用佈局
使用ViewStub懶加載佈局 (TODO:Android佈局技巧:使用ViewStub提升UI性能)
使用ViewHolder、Thread使ListView滾動更加流暢
其它優化點
合理使用異步操做
懶加載:當前不須要的數據,不要加載,即按需加載。懶加載的範圍是普遍的,能夠是數據,能夠是View,或者其它
使用緩存
圖片緩存:包括MemoryCache和DiskCache,推薦使用官方DEMO中的Cache
參考:DisplayingBitmaps Efficiently
單例數據緩存:創建一個管理數據的類,管理全部數據,當主界面消失後,因爲Application自己沒有實際退出,所以,數據自己也沒有釋放掉,下次啓動時,省去了加載數據的時間,固然,這並非一個好的行爲。
使用ListView、GridView的View緩存
使用Message自身的緩存,避免重複建立Message實例
線程池
數據池(可參考Message Pool的實現方式)
……
數據庫優化
SQL優化
創建索引
使用事務
…...
算法優化
用快速排序代替冒泡排序
用二分查找代替線性查找
……
數據結構使用
不要所有使用ArrayList,合理使用LinkedList等易於插入和刪除的集合
合理使用HashMap、HashSet來提升查找性能
使用SparseArray、SparseIntArray、SparseBooleanArray來替代某些特定的HashMap
……
其它策略
能夠考慮延遲處理,避免在同一時間幹過多的事情
應用程序內部的性能優化
該部分的優化應該是依據程序的不一樣而不一樣,沒有萬般皆準的法則,目前從我作過的程序來看,實際上,上述的性能優化點基本上已經可以解決不少性能問題了。
在我所作的程序中,主要的優化手段是:
程序邏輯簡化:分析代碼,去掉冗餘邏輯
數據結構的優化:對集合類的靈活使用,特別是HashMap的使用,極大的提升查找性能。
批量處理原則:對於須要循環調用地方,採用批量處理
總結
性能優化自己是對代碼的重構和反思過程,經過優化性能,能找出咱們不少設計、邏輯上的不足。
優化的過程每每很痛苦,但在作過這個過程後,我的在編程水平、設計水平上都會有很大的提升。
不少優化的思想應該作爲編碼規範的一部分,須要咱們反覆實踐,在寫代碼時,第一反應所得出的代碼就是最優的。