Java 應用性能優化是一個老生常談的話題,典型的性能問題如頁面響應慢、接口超時,服務器負載高、併發數低,數據庫頻繁死鎖等。尤爲是在「糙快猛」的互聯網開發模式大行其道的今天,隨着系統訪問量的日益增長和代碼的臃腫,各類性能問題開始紛至沓來。html
Java 應用性能的瓶頸點很是多,好比磁盤、內存、網絡 I/O 等系統因素,Java 應用代碼,JVM GC,數據庫,緩存等。java
筆者根據我的經驗,將 Java 性能優化分爲 4 個層級:應用層、數據庫層、框架層、JVM 層,如圖 1 所示。ios
每層優化難度逐級增長,涉及的知識和解決的問題也會不一樣。數據庫
好比應用層須要理解代碼邏輯,經過 Java 線程棧定位有問題代碼行等;緩存
數據庫層面須要分析 SQL、定位死鎖等;性能優化
框架層須要懂源代碼,理解框架機制;服務器
JVM 層須要對 GC 的類型和工做機制有深刻了解,對各類 JVM 參數做用瞭然於胸。網絡
圍繞 Java 性能優化,有兩種最基本的分析方法:現場分析法和過後分析法。併發
現場分析法經過保留現場,再採用診斷工具分析定位。現場分析對線上影響較大,部分場景(特別是涉及到用戶關鍵的在線業務時)不太合適。app
過後分析法須要儘量多收集現場數據,而後當即恢復服務,同時針對收集的現場數據進行過後分析和復現。下面咱們從性能診斷工具出發,分享搜狗商業平臺在其中的一些案例與實踐。
性能診斷一種是針對已經肯定有性能問題的系統和代碼進行診斷,還有一種是對預上線系統提早性能測試,肯定性能是否符合上線要求。本文主要針對前者,後者能夠用各類性能壓測工具(例如 JMeter)進行測試,不在本文討論範圍內。
針對 Java 應用,性能診斷工具主要分爲兩層:OS 層面和 Java 應用層面(包括應用代碼診斷和 GC 診斷)。
OS 的診斷主要關注的是 CPU、Memory、I/O 三個方面。
CPU 診斷
對於 CPU 主要關注平均負載(Load Average),CPU 使用率,上下文切換次數(Context Switch)。
經過 top 命令能夠查看系統平均負載和 CPU 使用率,圖 2 爲經過 top 命令查看某系統的狀態。
平均負載有三個數字:63.66,58.39,57.18,分別表示過去 1 分鐘、5 分鐘、15 分鐘機器的負載。按照經驗,若數值小於 0.7*CPU 個數,則系統工做正常;若超過這個值,甚至達到 CPU 核數的四五倍,則系統的負載就明顯偏高。圖 2 中 15 分鐘負載已經高達 57.18,1 分鐘負載是 63.66(系統爲 16 核),說明系統出現負載問題,且存在進一步升高趨勢,須要定位具體緣由了。
經過 vmstat 命令能夠查看 CPU 的上下文切換次數,如圖 3 所示:
上下文切換次數發生的場景主要有以下幾種:
1)時間片用完,CPU 正常調度下一個任務;
2)被其它優先級更高的任務搶佔;
3)執行任務碰到 I/O 阻塞,掛起當前任務,切換到下一個任務;
4)用戶代碼主動掛起當前任務讓出 CPU;
5)多任務搶佔資源,因爲沒有搶到被掛起;
6)硬件中斷。
Java 線程上下文切換主要來自共享資源的競爭。通常單個對象加鎖不多成爲系統瓶頸,除非鎖粒度過大。但在一個訪問頻度高,對多個對象連續加鎖的代碼塊中就可能出現大量上下文切換,成爲系統瓶頸。好比在咱們系統中就曾出現 log4j 1.x 在較大併發下大量打印日誌,出現頻繁上下文切換,大量線程阻塞,致使系統吞吐量大降的狀況,其相關代碼如清單 1 所示,升級到 log4j 2.x 才解決這個問題。
1 for(Category c = this; c != null; c=c.parent) { 2 // Protected against simultaneous call to addAppender, removeAppender,… 3 synchronized(c) { 4 if (c.aai != null) { 5 write += c.aai.appendLoopAppenders(event); 6 } 7 … 8 } 9 }
Memory
從操做系統角度,內存關注應用進程是否足夠,可使用 free –m 命令查看內存的使用狀況。經過 top 命令能夠查看進程使用的虛擬內存 VIRT 和物理內存 RES,根據公式 VIRT = SWAP + RES 能夠推算出具體應用使用的交換分區(Swap)狀況,使用交換分區過大會影響 Java 應用性能,能夠將 swappiness 值調到儘量小。由於對於 Java 應用來講,佔用太多交換分區可能會影響性能,畢竟磁盤性能比內存慢太多。
I/O
I/O 包括磁盤 I/O 和網絡 I/O,通常狀況下磁盤更容易出現 I/O 瓶頸。經過 iostat 能夠查看磁盤的讀寫狀況,經過 CPU 的 I/O wait 能夠看出磁盤 I/O 是否正常。若是磁盤 I/O 一直處於很高的狀態,說明磁盤太慢或故障,成爲了性能瓶頸,須要進行應用優化或者磁盤更換。
除了經常使用的 top、 ps、vmstat、iostat 等命令,還有其餘 Linux 工具能夠診斷系統問題,如 mpstat、tcpdump、netstat、pidstat、sar 等。Brendan 總結列出了 Linux 不一樣設備類型的性能診斷工具,如圖 4 所示,可供參考。
....
轉載:https://www.ibm.com/developerworks/cn/java/j-lo-performance-tuning-practice/index.html