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