linux进程实际内存大小,Linux进程内存用量分析之堆内存篇
本文將介紹幾種內存泄漏檢測工具,并通過實際例子介紹一種分析堆內存占用量的工具和方法,幫助定位內存膨脹問題。背景
進程的內存管理是每一個開發者必須要考慮的問題,對于C++程序進程來說,出現問題很多情況下都與內存掛鉤。進程崩潰問題通常可以使用gdb等調試工具輕松排查并解決。而對于進程內存膨脹這類問題,原因通常有三個:
1.內存泄漏。
2.分配器管理的空閑內存較多而造成的內存空洞。
3.有未統計使用的未知內存占用。
內存泄漏問題可以使用一些工具來檢測。但是對于后兩種問題,卻一直沒有比較通用的方法去確定。本文將介紹幾種內存泄漏檢測工具,并通過實際例子介紹一種分析堆內存占用量的工具和方法,幫助定位內存膨脹問題。常見內存問題的分析方法
對于內存泄露問題,目前已經有較成熟的工具進行檢測,這里簡單介紹兩個工具:AddressSanitizer和Valgrind。
AddressSanitizer是google開源項目,可以用來檢測內存泄漏和其他導致進程崩潰的內存問題。它的優勢在于造成的額外CPU占用很小,但是需要重新編譯項目,并且在編譯的時候添加-fsanitize=address選項。在程序運行時如果有任何內存問題,就會終止進程并且打印出詳細的錯誤信息。如果進程存在內存泄漏會在進程結束后,打印出所有泄漏的內存大小和申請這塊內存的調用棧,如下圖所示:
AddressSanitizer檢測內存泄漏
另一個工具Valgrind的優勢在于不需要重新編譯,只需要在運行時加上valgrind --leak-check=yes即可。但是它的額外CPU開銷會更大,大約是AddressSanitizer的十倍,功能上也不及AddressSanitizer完善。下表是兩種工具功能和性能的比較:
AddressSanitizer與Valgrind對比
這兩種工具不光能夠檢測內存泄漏,對于堆棧溢出等問題也有比較好的效果。對于這兩個工具更具體的介紹可以參照官方的使用文檔:
AddressSanitizer:https://github.com/google/sanitizers/wiki/AddressSanitizer
Valgrind:
而對于后兩種原因,我們需要根據不同的分配器區別看待。常見的分配器有glibc默認的ptmalloc,google維護的tcmalloc以及facebook維護的jemalloc等。后兩者都自帶了內存分析工具(Heap Profiler),可以檢測內存泄漏,也可以打印出詳細的內存分配情況,對上述三個問題都有比較完善的排查方法,有興趣可以查看官方文檔,都講得比較詳細,這里不再介紹。而glibc默認的ptmalloc卻不自帶這樣的工具,一種排查方法是去了解ptmalloc的實現和結構以后編寫程序或者gdb腳本去分析進程的內存結構,我們接下來要介紹的一種內存分析工具就是以這種方法實現的。針對ptmalloc的堆內存內用分析1.環境
58自研的搜索引擎Esearch底層使用C++實現。Esearch在內存管理方面針對不同的場景會有不同的策略。對于對象生命周期有規律,高頻分配的場景,Esearch實現了定制的內存池進行管理,并且這些內存都會在日志中統計占用量。而對于對象生命周期不確定,大小不確定的場景,內存池的代價可能高于通用分配器(new/malloc),所以直接使用通用內存分配器來分配。
對于通用分配器的選擇,目前Esearch使用的是glibc2.12環境下默認的ptmalloc。之所以未使用tcmalloc或者jemalloc是因為經測試后發現后兩者在常見場景下內存占用比ptmalloc要高,而且Esearch中對于內存分配熱點已經使用了定制內存池,后兩種分配器的優勢其實并不明顯。對于Ptmalloc完整結構的介紹可以閱讀源碼或者參閱華庭的《glibc內存管理ptmalloc2源代碼分析》,這里只在用到時闡述一下原理,不做過多的介紹。
接下來我們通過一個例子來了解如何分析堆內存的用量?,F在有一個realtime_searcher進程如下:
運行中的realtime_searcher進程
可見進程占用總物理內存27G,其中SHR內存占用18G,剩下的物理內存 約9G。
2.工具介紹
這里介紹一個非常強大的內存分析工具——core_analyzer。這是一個基 于core文件的內存分析工具,由Michael Yan開發和維護并且開源在github上。利用它可以對glibc層的ptmalloc結構進行分析,還原進程真實的內存結構。目前core_analyzer支持的glibc2.3,2.4,2.5,2.12-2.23版本下的ptmalloc實現,這些版本對應的ptmalloc結構其實都大同小異。
Core_analyzer工具提供了以下功能:
Core_analyzer用戶界面
[0] 打印core文件的基本信息,包括各個線程的信息,和內存段的信息等。
[1] 水平搜索對象的引用
[2] 垂直搜索對象的引用鏈,直到找到符號表中有調試信息的對象。
[3] 打印線程共享對象
[4] 打印給定地址段的內容
[5] 通過地址查詢所屬chunk
[6] 打印所給的地址周圍的頁(意義不明)
[7] 打印整個堆的結構。該結構能夠與ptmalloc的結構相對應
[8]、[9]都是打印前N大的chunk,[9]還順便打印出引用鏈
[10] 根據它的名字為內存泄漏檢測,但實際使用發現不僅耗時而且不正確
[11] 退出
總結
以上是生活随笔為你收集整理的linux进程实际内存大小,Linux进程内存用量分析之堆内存篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 列注释_机器学习 Pandas 03:基
- 下一篇: java tls 证书_在使用Java