目錄
一. 專案背景.............................................................................................................................................................................................................3
二.所遇到的挑戰......................................................................................................................................................................................................3
三.以OOM為例,講解下此類問題的解決步驟......................................................................................................................................................................................................3
1.什麼是OOM......................................................................................................................................................................................................3
2.如何檢視JVM虛擬機器的可用記憶體......................................................................................................................................................................................................4
3.如何監控和優化應用的記憶體情況......................................................................................................................................................................................................5
4.記憶體正常與異常情況對比......................................................................................................................................................................................................5
5.應用的記憶體優化......................................................................................................................................................................................................7
四.對IOS及React Native應用的監控......................................................................................................................................................................................................9
五.總結......................................................................................................................................................................................................10
附錄:《個人簡介》......................................................................................................................................................................................................11
一. 專案背景
在我司開發的某能源APP中,服務於多家用能企業員工。在這幾年的開發中,也著實遇到過很多使用者上報的反饋意見,但是有些問題的根源卻不得而知,有時候甚至需要對一個模組整體重構才解決問題,經過了這幾年迭代,將線上應用的一些實戰經驗分享於此。
在開發App過程中,經常會遇到OOM(out of memory)記憶體溢位的情況,本文將結合自己多年的開發經驗,探討下遇到效能問題的解決方案。
二.所遇到的挑戰
在我司上線的App和小程式中,會遇到很多併發的操作,尤其在App端更為嚴重,在有些控制操作時,往往受到網路波動、響應速度的影響,其操作經常會失敗、異常退出、甚至閃退等問題,遇到此類問題,往往是程式設計師頭疼的事,因為問題不好定位,不容易發現問題出現的位置。也給線上使用者帶來了不好的體驗。
雖然是2B的業務,短期雖不會對使用者量造成損失,但是如果長期解決不了此類問題,不少使用者的使用頻率逐漸下降。還有些類似手機端遠端智慧控制機器的場景,如果發生錯誤,可能呢還會造成不必要的經濟損失。
三.以OOM為例,講解下此類問題的解決步驟
1.什麼是OOM
在收集到的錯誤資訊中,先來看下OOM報錯時的樣子:
09-08 21:15:38.771: E/dalvikvm-heap(123452): Out of memory on a 20455736-byte allocation. 09-08 21:15:38.779: E/AndroidRuntime(23231): java.lang.OutOfMemoryError
這就是因為程式申請使用“20455736”byte 記憶體,但Java虛擬機器無法提供這麼大的記憶體,所以程式就被迫死掉了。
2.如何檢視JVM虛擬機器的可用記憶體
我們系統的記憶體不會全部給JVM虛擬機器來使用的,所以,我們需要得知真正的可用記憶體是多少,才能知道我們應該優化的方向。
在開發中,可以通過java 一下命令,來測試出,當前系統的可用記憶體
java -XmxXXXXM -version
如: 執行命令java -Xmx2000M -version,如果顯示出java的版本資訊,則說明2000M記憶體是可用的。
如此這般,可以一直修改記憶體大小來測試,直到顯示出:
出現上圖內容,說明記憶體已經超出了JVM可用的記憶體了,那這個記憶體就是當前JVM的最大記憶體。
我們可以根據模擬器設定的記憶體大小,計算出能供給應用使用的記憶體大小了。不同的機型,記憶體也不一樣大,要確保主流機型偏下的配置,能夠正常流暢的執行程式。
3.如何監控和優化應用的記憶體情況
不管是Android APP還是Java程式我們都可以通過監控該APP在JVM中的執行情況,來判斷是否出現異常。
我們可以通過JDK監視和管理控制檯(jconsole.exe),在安裝目錄:jdk/bin。
通過此平臺,可以監控應用的執行情況,佔用記憶體情況,已經是否出現死鎖的執行緒,如下圖:
4.記憶體正常與異常情況對比
記憶體使用正常的應用,其記憶體監控應該是下圖這樣:
有記憶體問題的應用,其記憶體曲線是這樣的(持續遞增,不會下降):
上圖,表示應用記憶體從啟動後,一直遞增,垃圾回收後,記憶體依然供不應求。那麼曲線的終點就是應用發生OOM的極限附近值了。
5.應用的記憶體優化
記憶體優化的目的,就是通過我們對JVM引數的調整,讓應用所使用的記憶體,能夠很好的回收,長期執行也不會出現記憶體只增不減的現象。
①.優化老生代記憶體佔比
如果Old GC佔用的記憶體一直遞增,且佔比較大,我們可以通過優化JVM引數,將-XX:NewRatio值設定為4,意味著:新生代佔1,老年代佔4,年輕代佔整個堆的1/5。這樣優化,多分配給GC 老年代的一些記憶體。
SurviorRatio也設定為4,即設定Eden區的比例佔多少,S0/S1相同。
②.提高survivor區的目標使用率
設定survivor區的目標使用率,當使用率達到時重新調整TenuringThreshold值,讓物件儘早的去old區。
-XX:TargetSurvivorRatio:一個計算期望Survivor區存活大小(Desired survivor size)的引數。預設值為50,即50%
-XX:TargetSurvivorRatio=50 (預設為50,即達到)
物件進入Survivor區之後,由於使用的是預設的自適應策略,導致當年齡為1的時候,Minor GC1次,就被移動到老年代了。導致老年代記憶體消耗過快,在併發場景下,一會就發生一次FGC。
我們可以增大該值,
-XX:TargetSurvivorRatio=90
③.調高程式執行期間的最大記憶體
如果通過優化後,程式在某些耗費資源的時間點,依然需要很大的記憶體,那麼我們只能調高JVM中應用執行的最大記憶體。
-Xmx1024M
④.選擇最佳的垃圾回收演算法
不同垃圾回收方法測試資料,在第①步和第②步中,我們實際是一點點的測試,最後確定使用哪種方案的,多次試驗記錄:
四.對IOS及React Native應用的監控
上述提到動監控工具以及優化策略都是針對基於Java平臺的,那麼像IOS和React Native開發的應用該怎樣監控呢?如何瞭解這些應用執行時,發生了哪些錯誤和異常呢?如何將這些錯誤收集,轉入到開發人員的Bug修復計劃中呢?
在這推薦一款應用效能監控平臺U-APM:
在此平臺上,我們可以實時監控當天應用出現的異常,並且有完整的統計發成的異常以及異常數、機型、版本號、應用下載來源市場、作業系統、使用者地域。也有關於應用對各個機型的記憶體的佔用情況,我們用再多的模擬器和真機測試,也抵不上真實的使用者的大資料。
友盟U-APM移動應用效能監控平臺提供的崩潰、卡頓、啟動、記憶體、網路等分析資料,可以全方位覆蓋開發人員還原Bug的各項指標,幫助開發人員快速定位和修復bug。
五.總結
1、效能調優要做到有的放矢,需要根據實際業務系統的特點,以一定時間的JVM日誌記錄為依據,進行有針對性的調整、比較和觀察。
2、效能調優是個及其耗時且無止境的過程,要綜合權衡調優成本(包含人力成本)和更換硬體成本的大小,來換取使用者體驗。
3、效能調優不僅僅包括JVM的調優,還有伺服器硬體配置、作業系統引數、中介軟體執行緒池、資料庫連線池、資料庫本身引數以及具體的資料庫表、索引、分割槽等的調整和優化。
4、通過特定工具(應用效能監控平臺U-APM)檢查程式碼中存在的效能問題並加以修正是一種比較經濟快捷的調優方法,上工治未病,不能等到使用者反饋,開發人員才遲遲發現問題。所以,監控平臺一定要上,將平臺捕捉到的異常,修復和優化在使用者感知之前。
附錄:《個人簡介》
本人目前就職於某上市能源企業,從事網際網路開發行業7年,在移動開發方向,參與過兩款Android APP和RN小程式,在其中擔任APP架構設計和主要開發人員。目前負責能源網際網路數字化轉型相關工作,對物聯網資料平臺、監控平臺、能源管理平臺等應用有多年經驗,對資料治理、資料管理、應用開發、平臺運維都深有涉及。
業餘時間,喜閱讀,學習不限於計算機領域的知識。常撰寫部落格,分享技術和從業知識,與同行探討技術細節。