大型網站技術架構演進與性能優化(五) 五、應用程序優化:代碼級優化

五、應用程序優化:代碼級優化
1、優化思路
做優化首先要知道從哪裏入手,也就是要知道系統的瓶頸在哪裏。一個請求會消耗很多資源:CPU、內存、網絡、磁盤等。這些資源中總會有一個到達瓶頸,只有優化最先到達瓶頸的資源纔會產生效果。
壓測工具
Java有兩個經典的代碼熱點分析工具:JProfiler和Yourkit
Apache ab壓測工具
這些具體使用參考文檔。
發現瓶頸
Jstack,可以看看當前的Java線程
壓測請求不是本機,要注意TCP連接數,可以使用netstat命令
檢查網卡是否達到了瓶頸
I/O也可能成爲瓶頸
2、影響性能的因素
所謂提升性能,通常意義上就是提升系統的QPS,即提升系統的吞吐量。
要提升系統的QPS,首先要了解QPS與RT的關係。
QPS與性能的關係
支持的線程數越多QPS越高,這隻在一定範圍內適用。
影響線程數量的兩個主要因素是CPU數量和線程等待時間。
對於大部分的Web系統,RT(response tiime)一般由CPU執行時間和線程等待時間(遠程RPC調用、I/O等待、sleep、wait等)組成。
減少CPU的執行時間對QPS有實質的提升,減少線程的等待時間對QPS提升不明顯。
設置最佳線程數
所謂最佳線程數是指消耗完服務器的瓶頸資源的一個臨界線程數量。
最佳線程數=[(線程等待時間+線程CPU時間)/線程CPU時間]/CPU數量。
如何才能獲取最佳線程數?
第一,單用戶壓測,查看CPU的消耗的百分比,然後直接乘以該百分比,再進行壓測。
第二,通過慢慢增加併發請求來進行性能壓測,通過觀察壓測結果判斷是否達到服務器的資源瓶頸,以獲得最佳線程數量。
最佳內存設置
處理併發請求要考慮內存的設置,即每個請求需要消耗多少內存、併發請求書乘以消耗的內存就是總內存的大小,如果設置的內存小於這個數,就會導致頻繁的Full GC。
如何判斷是否達到內存瓶頸?壓測時觀察Old區內存增長是否正常。
如何計算出每個請求平均佔用的內存大小呢?理論上通過Eden/(QPS * minorGC的平均間隔時間(s))來計算。
如何減少每次請求中佔用的內存大小呢?
儘量減少線程請求生命週期裏的對象數量。
對象創建到可回收的時間要儘可能短,例如不要在非常耗時的操作前面創建一個大對象,而儘可能在真正使用這個對象時再創建,對象使用完成後也要儘量置空。
如何提升性能
如果要提升服務器端的響應時間RT,採用減少I/O的時間能達到最佳效果,比如合併多個I/O請求。
如果要提升QPS,採用優化CPU的時間能達到最佳效果。
3、Java特性的優化
比如,常用StringBuilder、優化自定義hashCode()、equals()、toString()方法,優先使用原始數據類型,不在循環中使用try…catch,copy時使用System.arraycopy()命令。
減少編碼
使用局部變量
減少方法調用
4、減少併發衝突
併發衝突往往會導致程序性能上不去,成爲性能瓶頸。
容易出現併發的地方一般都會用鎖,判斷是否出現鎖衝突要查看CPU沒用滿的情況下QPS是否還能上去,可以通過jstack檢查線程是否都在block狀態。
5、減少序列化
序列化也是Java性能的一大天敵,減少Java中的序列化操作也能大大提升性能。
序列化大部分是在RPC調用中發生的,因此避免或者減少RPC的調用就可以減少序列化,當然當前的序列化協議已經做了很多優化提升性能。
6、減少字符到字節的轉換
每個字符的編碼都需要查表,而這種操作非常耗CPU資源,所以減少字符到字節的轉換或者相反、減少字符編碼會非常有效。
讀取靜態文件,一般情況下,我們會把靜態文件讀取到內存,以減少每次從磁盤讀文件的消耗,但是還可以進一步做的就是把這個靜態文件直接轉化成字節緩存,也就是把String經過編碼轉換成byte[]數組,當然我們輸出的時候要用stream輸出而不是用out.print()。
7、使用長連接
在內部調用中,會有一些HTTP請求,大部分情況以短連接爲主。
8、總結
a、發現短板
主要考慮以下場景會受到一些限制:光速、網速、網絡結構和應用本身的一些瓶頸等。
b、減少數數據大小
有兩個地方特別影響性能,一是服務端在處理數據時不可避免地存在字符到字節的相互轉化;而是HTTP請求時要做Gzip壓縮,網絡傳輸的耗時,這些都和數據大小密切相關。
從以下方面減少數據大小:
HTML、圖片、JSON、JSON結構、Java對象、請求數。
c、數據分級
就是要保證首屏爲先、重要信息未先,次要信息採用異步加載的方式,提升用戶獲取數據的體驗。
d、減少中間環節,減少字符到字節的轉換,將變的轉換爲不變的;增加預處理就是去掉不需要的操作。
要做好優化還需要做好應用基線,大概包括以下內容:
性能基線,何時性能突然下降;
成本基線,去年雙11用了多少臺機器;
鏈路基線,系統發生了哪些變化;
持續關注系統的性能,代碼級(提升代碼質量),業務(改掉不合理的調用),架構和鏈路級(改進架構);
用更通用和批量的方式解決問題,整合系統之間的調研鏈路(合併部署),提升整體機器使用率(彈性部署)。

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