1. 程式人生 > >效能測試瓶頸分析之記憶體洩漏

效能測試瓶頸分析之記憶體洩漏

關於記憶體洩漏,相信大家都不陌生,壓力測試中經常會出現,本人最近在做一個壓力測試中就著實體會了一下,上來分享分享。

  記憶體洩露是指程式中間動態分配了記憶體,但是在程式結束時沒有釋放這部分記憶體,從而造成那一部分記憶體不可用的情況,重起計算機可以解決,但是也有可能再次發生記憶體洩露,記憶體洩露和硬體沒有關係,它是由軟體設計缺陷引起的。

  以發生的方式來分類,記憶體洩漏可以分為4類:

  1. 常發性記憶體洩漏。發生記憶體洩漏的程式碼會被多次執行到,每次被執行的時候都會導致一塊記憶體洩漏。

  2. 偶發性記憶體洩漏。發生記憶體洩漏的程式碼只有在某些特定環境或操作過程下才會發生。常發性和偶發性是相對的。對於特定的環境,偶發性的也許就變成了常發性的。所以

測試環境測試方法對檢測記憶體洩漏至關重要。

  3. 一次性記憶體洩漏。發生記憶體洩漏的程式碼只會被執行一次,或者由於演算法上的缺陷,導致總會有一塊僅且一塊記憶體發生洩漏。比如,在類的建構函式中分配記憶體,在解構函式中卻沒有釋放該記憶體,所以記憶體洩漏只會發生一次。

  4. 隱式記憶體洩漏。程式在執行過程中不停的分配記憶體,但是直到結束的時候才釋放記憶體。嚴格的說這裡並沒有發生記憶體洩漏,因為最終程式釋放了所有申請的記憶體。但是對於一個伺服器程式,需要執行幾天,幾周甚至幾個月,不及時釋放記憶體也可能導致最終耗盡系統的所有記憶體。所以,我們稱這類記憶體洩漏為隱式記憶體洩漏。

  本人最近就在對一個Http應用進行壓力測試,發現被測試的物件程序在併發100時記憶體佔用達到20%,當壓力到達1000的時候,記憶體就持續上升,達到60%,最後壓力結束後,記憶體仍舊停留在60%的使用率,然後重啟了系統發現記憶體已經恢復了正常,於是在第二輪測試時再次不斷加壓,同時關注

效能計數器中的如下指標

  Memory\ Available Bytes 是指剩餘的可用實體記憶體,單位是兆位元組(參考值:>=10%)。表明程序當前可使用的記憶體位元組數。

  Memory\ Pages/sec 是表明由於硬體頁面錯誤而從磁碟取出的頁面數,或由於頁面錯誤而寫入磁碟以釋放工作集空間的頁面數。

  Process\Private Bytes 是指當前程序中執行的私有記憶體,如果此記憶體不斷攀升,表示當前存在的記憶體洩漏,一般情況如果資源合理利用的話,該指標值波動比較平穩。

  通過有效的監控以上計數器可以方便我們判斷記憶體洩漏問題,同時需要開發人員配合進行記憶體查詢,定位分析哪些程式存在記憶體洩漏。最後通過

開發人員的除錯,問題很快定位了,確實有程式沒有釋放記憶體,最後再次施壓的結果是記憶體持續在一個值上下波動,一般參考值在20%左右,不過這個根據具體的記憶體空間來定,當然如果可以更小最好了,表明記憶體合理利用和分配。當然了,檢測記憶體洩漏的方式很多,施壓是可以結合響應時間的曲線圖來監控也可。

  從使用者使用程式的角度來看,記憶體洩漏本身不會產生什麼危害,作為一般的使用者,根本感覺不到記憶體洩漏的存在。真正有危害的是記憶體洩漏的堆積,這會最終消耗盡系統所有的記憶體。從這個角度來說,一次性記憶體洩漏並沒有什麼危害,因為它不會堆積,而隱式記憶體洩漏危害性則非常大,因為較之於常發性和偶發性記憶體洩漏它更難被檢測到。對於開發人員來說,熟悉javaC++等應該都瞭解,通常我們定義一些變數,或者例項化一些物件,比較常用就是new方法,然後通過delete方法進行銷燬,如果定義的東西比較多了,也就是想一天申請的記憶體空間就多了,如果一旦沒有合理的管理和消化,就會忘記最後做一些記憶體回收的處理,導致一些變數和例項物件沒有處理掉,最後在程式執行一段時間之後就發現我們的記憶體不斷在攀升,長時間下來積累了就佔用了大量的記憶體空間,導致其他程序無法獲取到記憶體資源,無法去處理其他應用,最後服務就shut down,等等之類情況都比較多見,不過這些也基本取決於開發人員的經驗所致,在程式編寫過程中合理的使用和管理記憶體是非常重要的,因為此類問題一般只有在效能測試中體現出來,功能測試是完全沒有表現的跡象。

  其實,記憶體洩漏問題多半在壓力測試中出現也是源於程式編寫過程中沒有規範化管理所導致,開發人員需要結合記憶體監測工具來有效監控自己的程式,這樣才會避免這些個低階的瓶頸出現,所以說效能測試只是為程式提供優化建議,而不應該成為幫助開發人員除錯程式的一種手段。