國內一線架構師的Java性能優化思路

性能優化是一個老生常談的問題了,典型的性能問題如頁面響應慢、接口超時,服務器負載高、併發數低,數據庫頻繁死鎖等。而造成性能問題又有很多種,比如磁盤I/O、內存、網絡、算法、大數據量等等。我們可以大致把性能問題分為四個層次:代碼層次、數據庫層次、算法層次、架構層次。

下面我結合實際性能優化案例,和大家分享下性能調優的工具、方法和技巧

國內一線架構師的Java性能優化思路

心態

說到性能問題,你可能首先就想到的是麻煩或者頭大,因為一般性能問題都比較緊急,輕則影響客戶體驗,重則宕機導致財務損失,而且性能問題比較隱蔽,不易發現。因此一時間無從下手,而這時我們就很容易從心底開始去排斥它,不願接這燙手的山芋。

而恰巧,性能調優是體現程序員水平的一個重要指標。

因為處理bug、崩潰、調優、入侵等突發事件比編程本身更能體現平庸程序員與理想程序員的差距。當面對一個未知的問題時,如何定位複雜條件下的核心問題、如何抽絲剝繭地分析問題的潛在原因、如何排除干擾還原一個最小的可驗證場景、如何抓住關鍵數據驗證自己的猜測與實驗,都是體現程序員思考力的最好場景。是的,在衡量理想程序員的標準上,思考力比經驗更加重要。

所以,若你不甘平庸,請擁抱性能調優的每一個機會。當你擁有一個正確的心態,你所面對的性能問題就已經解決了一半。

技巧

拿到一個性能問題,不要忙著先上工具,先了解問題出現的背景,問題的嚴重程度。然後大致根據自己的經驗積累作出預估。比如客戶來了個性能問題說系統宕機了,已經造成資金損失了。這種涉及到錢的問題,大家都比較敏感,根據自己的level,決定是否要接這個鍋。這不是逃避,而是自知之明。

瞭解問題背景之後,下一步就來嘗試問題重現。如果在測試環境能夠重現,那這種問題就很好跟蹤分析。如果問題不能穩定重現或僅能在生產環境重現,那問題就相對比較棘手,這時要立刻收集現場證據,包括但不限於抓dump、收集應用程序以及系統日誌、關注CPU內存情況、數據庫備份等等,之後不妨再嘗試重現,比如恢復客戶數據庫到測試環境重現。

不管問題能否重現,下一步,我們就要大致對問題進行分類,是代碼層次的業務邏輯問題還是數據庫層次的操作耗時問題,又或是系統架構的吞吐量問題。那如何確定呢?而我傾向於先從數據庫動手。我的習慣做法是,使用數據庫監控工具,先跟蹤下Sql耗時情況。如果監控到耗時較長的SQL語句,那基本上就是數據庫層次的問題,否則就是代碼層次。若為代碼層次,再研究完代碼後,再細化為算法或架構層次問題。

確定問題種類後,是時候上工具來精準定位問題點了:

  • Sql耗時問題,推薦使用免費的Plan Explorer分析執行計劃。
  • 代碼問題定位,優先推薦使用VS自帶的Performance Analysis,其次是RedGate的性能分析套件.NET Developer Bundle;然後還有Jet Brains的dotTrace — .NET performance profiler,dotMemory– .NET memory profiler;再然後就是反人類的Windbg;等等。

精準定位問題點後,就是著手優化了。相信到這一步,就是優化策略的選擇了,這裡就不展開了。

優化後,最後當然要進行測試了,畢竟優化了多少,我們也要做到心裡有譜才行。

以上囉囉嗦嗦有點多,下面我們直接上案例。

代碼優化案例

客戶反饋銷售訂單100條分錄行,保存進行可髮量校驗時,耗時7mins左右。

拿到這個問題後,本地重現後,監控sql耗時沒有異常,那就著重分析代碼了。因為可髮量校驗的業務邏輯極其複雜,又加上又直接再一個類文件實現該功能,3500+行的代碼,加上零星註釋,真是讓人避之不及。逃避不是辦法,還是上工具分析一把。

這次我選用的時VS自帶的Performance Profiler,開發環境下極其強大的性能調優工具。針對我們當前案例,我們僅需要跟蹤指定服務對應的dll即可,使用步驟如下:

  1. Analyze–>Profiler–>New Performance Session
  2. 打開Performance Explorer
  3. 找到新添加的Performance Session,右鍵Targets,然後選擇Add Target Binary,添加要跟蹤的dll文件即可
  4. 將應用跑起來
  5. 選中Performance Session,右鍵Attach對應進程即可跟蹤分析性能了
  6. 在跟蹤過程中,可隨時暫停跟蹤和停止跟蹤
國內一線架構師的Java性能優化思路

跟蹤結束後本案例跟蹤到的採樣結果如下圖:

國內一線架構師的Java性能優化思路

同時Performance Profiler也給出了問題的建議,如下圖:

國內一線架構師的Java性能優化思路

其中第1、4條大致說明程序I/O消耗大,第一代的GC上存在未及時釋放的垃圾佔比過高。而根據上圖的採樣結果,我們可以直接看出是由於再代碼中頻繁操作DataTable引起的性能瓶頸。走讀代碼發現的確如此,所有的數量統計都是在代碼中循環遍歷DataTable進行處理的。而最終的優化策略,就相當於一次大的重構,將所有代碼中通過遍歷DataTable的計算邏輯全部挪到SQL中去做。由於代碼過多,就不再放出。

算法優化案例

某全流程跟蹤報表超時。

這個報表是用來跟蹤所有單據從下單到出庫的業務流程數據流轉情況。而所有的流程數據都是按照樹形結果存儲在數據庫表中的,類似這樣:

國內一線架構師的Java性能優化思路

圖中的流程為:

銷售合同–>銷售訂單–>發貨通知單–>銷售出庫單

為了構造流程圖,之前的處理方法是把流程數據取回來,通過代碼構造流程圖。這也就是性能差的原因。

而針對這種情況,就是考驗我們平時經驗積累了。對於樹形結構的表,我們也是可以通過SQL來進行直接查詢的,這就要用到了SQL Server的CTE語法來進行遞歸查詢。

總結

性能調優是一個循序漸進的過程,不可能一蹴而就,重在平時的點滴積累。

總結下我的調優思路

  • 調整心態,積極應對
  • 瞭解性能背景, 收集證據, 嘗試重現
  • 問題分類,先監控SQL耗時,大致確定是SQL或是代碼層次原因
  • 使用性能分析工具,確定問題點
  • 調優測試

那如何學習才能快速入門並精通呢?

當真正開始學習的時候難免不知道從哪入手,導致效率低下影響繼續學習的信心。

但最重要的是不知道哪些技術需要重點掌握,學習時頻繁踩坑,最終浪費大量時間,所以有一套實用的視頻課程用來跟著學習是非常有必要的。

為了讓學習變得輕鬆、高效,今天給大家免費分享一套阿里架構師傳授的一套教學資源。幫助大家在成為架構師的道路上披荊斬棘。

這套視頻課程詳細講解了(Spring,MyBatis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化、分佈式架構)等這些成為架構師必備的內容!

而且還把框架需要用到的各種程序進行了打包,根據基礎視頻可以讓你輕鬆搭建分佈式框架環境,像在企業生產環境一樣進行學習和實踐。

國內一線架構師的Java性能優化思路

後臺私信回覆“架構” 就可以馬上免費獲得這套價值一萬八的內部教材!

最後,做一個愛思考,懂思考,會思考的程序員。


分享到:


相關文章: