LINUX性能調優---內存(內存泄漏)

當進程通過 malloc() 申請虛擬內存後,系統並不會立即爲其分配物理內存,而是在首次訪問時,才通過缺頁異常陷入內核中分配內存。
爲了協調 CPU 與磁盤間的性能差異,Linux 還會使用 Cache 和 Buffer ,分別把文件和磁盤讀寫的數據緩存到內存中。
對應用程序來說,動態內存的分配和回收,是既核心又複雜的一個邏輯功能模塊。管理內存的過程中,也很容易發生各種各樣的“事故”,比如,
沒正確回收分配後的內存,導致了泄漏。
訪問的是已分配內存邊界外的地址,導致程序異常退出,等等。
特別是對於C語言這種需要程序員自己管理內存的編程語言,一不小心就會發生內存泄漏的問題。在應用程序中,會使用智能指針,內存池的技術來避免發生內存泄漏的問題。
內存的分配和回收
用戶空間是分段的。比如只讀段、數據段、堆、棧以及文件映射段等。這些內存段正是應用程序使用內存的基本方式。
如果你在程序中定義了一個局部變量,比如一個整數數組 int data[64] ,就定義了一個可以存儲 64 個整數的內存段。由於這是一個局部變量,它會從內存空間的棧中分配內存。
棧是有系統直接管理的,當變量超出了他的作用域系統就會回收這個變量的內存。
堆是由程序員管理的,分配和回收都由程序員自己搞定。如果應用程序沒有正確釋放堆內存,就會造成內存泄漏。
只讀段,包括程序的代碼和常量,由於是隻讀的,不會再去分配新的內存,所以也不會產生內存泄漏。
數據段,包括全局變量和靜態變量,這些變量在定義時就已經確定了大小,所以也不會產生內存泄漏。
內存映射段,包括動態鏈接庫和共享內存,其中共享內存由程序動態分配和管理。所以,如果程序在分配後忘了回收,就會導致跟堆內存類似的泄漏問題。
內存泄漏的危害非常大,這些忘記釋放的內存,不僅應用程序自己不能訪問,系統也不能把它們再次分配給其他應用。雖然,系統最終可以通過 OOM (Out of Memory)機制殺死進程,但進程在 OOM 前,可能已經引發了一連串的反應,導致嚴重的性能問題。比如應用非配了過多的內存,導致整個系統的內存不夠用,就會引發SWAP交換,嚴重影響系統性能。
實驗環境
1 ubuntu 18.04
2 2核心 4G
3 安裝
Install bcc
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4052245BD4284CDD
echo “deb https://repo.iovisor.org/apt/bionic bionic main” | sudo tee /etc/apt/sources.list.d/iovisor.list
sudo apt-get updatesudo apt-get install -y bcc-tools libbcc-examples linux-headers-$(uname -r)
步驟:
編譯測試程序
gcc -o main.c memleak
啓動 ./memleak
我們應該怎麼檢查內存情況,判斷有沒有泄漏發生呢?
內存泄漏問題,我們更應該關注內存使用的變化趨勢,那麼就可以採用vmestat
在這裏插入圖片描述
未使用內存在逐漸減小,而 buffer 和 cache 基本不變,這說明,系統中使用的內存一直在升高。但這並不能說明有內存泄漏,因爲應用程序運行中需要的內存也可能會增大。比如說,程序中如果用了一個動態增長的數組來緩存計算結果,佔用內存自然會增長。
介紹一個新工具:memleak
memleak 可以跟蹤系統或指定進程的內存分配、釋放請求,然後定期輸出一個未釋放內存和相應調用棧的彙總情況(默認 5 秒)。
/usr/share/bcc/tools/memleak -a -p $(pidof app)在這裏插入圖片描述
可以看到在leak函數裏面發生了內存泄漏。
通過查找代碼,發現程序裏面確實只是申請了沒有釋放。
加上一行釋放代碼,搞定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章