std::map的clear()沒有用?


昨天晚上,我徒弟跑過來講,他的程序的內存占用居高不下,願意是std::map的clear()沒有效果。於是我讓他用erase(begin,end); 試試也不行。

代碼如下:

void release_map(void)
{
    map<int,string> testmap;
    for(int i=0; i<1000000; i++)
    {
        testmap.insert(make_pair(i,"abc"));
    }
    testmap.clear();
}

int main()
{
    release_map();
    while(1)
    {
        sleep(1);
    }
return 0;
}
View Code

用命令 top -p `ps -ef | grep abc | grep -v grep | awk {'print $2'}`, 一查看,占了104M物理內存。

開始我猜測是stl用了自己的緩沖池,clear()並沒有歸還給系統。於是我用了boost::unordered_map試試,一查看,占了78M物理內存(看來hashmap比紅黑樹既快又省空間)。

於是上網查詢資料,stl有很多種allocator,默認采用是的new_allocator,並沒有使用內存緩沖池,針對不同的應用場合,STL中實現了不同的Allocator

__gnu_cxx::new_allocator<T> Simply wraps ::operator new and ::operator delete.
__gnu_cxx::malloc_allocator<T> Simply wraps malloc and free. There is also a hook for an out-of-memory handler
__gnu_cxx::debug_allocator<T> A wrapper around an arbitrary allocator A. It passes on slightly increased size requests to A, and uses the extra memory to store size information. 
__gnu_cxx::__pool_alloc<bool, int> A high-performance, single pool allocator. The reusable memory is shared among identical instantiations of this type.
__gnu_cxx::__mt_alloc<T> A high-performance fixed-size allocatorthat was initially developed specifically to suit the needs of multi threaded applications
__gnu_cxx::bitmap_allocato A high-performance allocator that uses a bit-map to keep track of the used and unused memory locations

發現stl提供的malloc.h有監控功能,於是修改為下面代碼:

#include <iostream>
#include <string>
#include <map>
#include <boost/unordered_map.hpp>
#include <malloc.h>

using namespace std;
using namespace boost;
void release_map(void)
{
    malloc_stats();
    map<int,string> testmap;
    sleep(2);
    for(int i=0; i<1000000; i++)
    {
        testmap.insert(make_pair(i,"abc"));
    }
    malloc_stats();
    testmap.clear();
    malloc_stats();
}

int main()
{
    release_map();
    getchar();
    return 0;
}
View Code

發現clear() 其實已經歸還內存了,內存的持有是 system bytes 。顯然,malloc並沒有把這些內存歸還給系統,而是緩存起來了。所以說,這個例子的罪魁禍首並不是STL,而是glibc的malloc。好吧,既然找到問題,那就要解決它,雖然glibc的緩存也是一番好意,但是由於實際運行環境不能等到什么用戶heap空間內連續空閑內存數據超出一個閾值時才將這片內存歸還給內核。

glibc管理內存目前采用的是ptmalloc2,我測試了google的tcmalloc和Jason Evans的jemalloc。

測試很簡單,把包downlaod下來並解壓,./configure && make && make install即可。

export $LD_PRELOAD="/usr/local/lib/libtcmalloc.so” 或者 export $LD_PRELOAD="/usr/local/lib/libjemalloc.so” (這個要根據自己的實際情況選擇路徑)

然后編譯后可以用ldd查看程序的依賴庫。

測試結果:tcmalloc也不歸還給系統,而jemalloc的clear后不再占用物理內存。

徒弟問了一句jemalloc靠譜么,我想想淘寶的Tengine,facebook的folly,redis,firefox,freebsd都是用這個,應該是很靠譜的。你上線去測試看看。

附上一張內存分配性能比較圖片:

 

參考文獻:

http://blog.163.com/dengminwen@126/blog/static/870226720097189486788/

http://bbs.chinaunix.net/thread-2195511-1-1.html

http://wangkaisino.blog.163.com/blog/static/1870444202011431112323846/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM