昨天晚上,我徒弟跑过来讲,他的程序的内存占用居高不下,愿意是std::map的clear()没有效果。于是我让他用erase(begin,end); 试试也不行。

代码如下:

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

用命令 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();
for(int i=; i<; i++)
{
testmap.insert(make_pair(i,"abc"));
}
malloc_stats();
testmap.clear();
malloc_stats();
} int main()
{
release_map();
getchar();
return ;
}

发现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/

std::map的clear()没有用?的更多相关文章

  1. C++ std::map

    std::map template < class Key, // map::key_type class T, // map::mapped_type class Compare = less ...

  2. std::map用法

    STL是标准C++系统的一组模板类,使用STL模板类最大的好处就是在各种C++编译器上都通用.    在STL模板类中,用于线性数据存储管理的类主要有vector, list, map 等等.本文主要 ...

  3. 由STL map调用clear后,内存不返还给操作系统的问题出发,探讨glibc malloc/free行为(转)

    1. 问题 我们的程序有几十个线程,每个线程拥有一个std::map,每个线程都要向自己的std::map中插入大量的数据,但每个数据只有几十字节:当使用完std::map,调用map.clear() ...

  4. C++ std::map::erase用法及其陷阱

    1.引入: STL的map中有一个erase方法用来从一个map中删除制定的节点 eg: map<string,string> mapTest; typedef map<string ...

  5. std::map

    1.例: map<int,string> m_mapTest; m_mapTest.insert(make_pair(1,"kong")); m_mapTest.ins ...

  6. std::map的操作:插入、修改、删除和遍历

    using namespace std; std::map<int,int> m_map; 1.添加 for(int i=0;i<10;i++) { m_map.insert(mak ...

  7. Using std::map with a custom class key

    From: https://www.walletfox.com/course/mapwithcustomclasskey.php If you have ever tried to use a cus ...

  8. Std::map too few template arguments

    在上述的代码中,红色波浪线的部分编译的时候报错: error C2976: 'std::map' : too few template arguments 换成std::map<std::str ...

  9. 使用std::map和std::list存放数据,消耗内存比实际数据大得多

    使用std::map和std::list存放数据,消耗内存比实际数据大得多 场景:项目中需要存储一个结构,如下程序段中TEST_DATA_STRU,结构占24B.但是使用代码中的std::list&l ...

随机推荐

  1. version `GLIBC_2.17' not found

    @ 今天把一个linux程序布到线上服务器上时,运行不起来,下面是解决思路. @ 运行程序,报以下错误 root@iZ25uck2l28Z:/tmp/tmp# ./speed_test ./speed ...

  2. MySQL 记录不存在时插入 记录存在则更新的实现方法

    INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1; INSERT 中 ON DUPLICATE KEY UP ...

  3. Lucene搜索方法总结

    转自:summerbell http://www.iteye.com/topic/569358 1.多字段搜索 使用 multifieldqueryparser 可以指定多个搜索字段. query q ...

  4. activeform 配置

    <?php $form = ActiveForm::begin([ 'action' => ['/admin/admin/adminadd'], 'id' => 'login-for ...

  5. CSS兼容性

    1,浮动 ie6中,设置浮动的元素,width自动包裹内容了.通常我们要设定一下这个元素的宽度 子元素浮动父容器高度不能自适应的CSS解决方法 网页前端工作者经常会遇到子元素设置float浮动后导致父 ...

  6. 换行符javajava去除字符串中的空格、回车、换行符、制表符

    在改章节中,我们主要介绍换行符java的内容,自我感觉有个不错的建议和大家分享下     每日一道理 只有启程,才会到达理想和目的地,只有拼搏,才会获得辉煌的成功,只有播种,才会有收获.只有追求,才会 ...

  7. maven编译项目理解

    如何运行这个Web项目? 右键项目名称,在弹出的选项中选择 Run As => Maven install,然后 Eclise 会下载并安装相关依赖包.在等待一段时间后,构建成功的结果如下:

  8. GDC2016【彩虹六号:围攻 】使丰富的“突破”成为可能的破坏系统

      [彩虹六号:围攻 ]使得丰富的“突破”成为可能的破坏系统 深奥的战术游戏的背景下,最新的程序化破坏技术[REALBLAST]!     进行演讲的是Ubisoft Montreal的Julien ...

  9. Sublime Text3 中文汉化

    首先安装Package Control,如果已经安装过可以跳过此步骤.可以按照官网这里https://packagecontrol.io/installation 复制命令或者直接复制下面: impo ...

  10. Solr 连接数据库

    实际工程应用中,从数据库导出数据创建索引再常见不过了,现在实验一下从数据库导入数据创建索引. 一.版本说明 Solr版本:4.7.0 数据库:sqlserver2005 二.配置步骤 1.  准备的j ...