大家都用过什么内存池?

可见一斑 2012-06-24 08:02:43
我以前做过的项目对稳定性有很高的要求,又用到了STL,boost,所以用过的内存池都有allocator的功能。最开始用过boost::pool_allocator,但是那个效率实在不敢恭维,某些代码的效率只有默认allocator的1/300,即使优化也很难赶上默认allocator的速度。后来我自己写了一个,效率虽然上去了,但还是有很多不完善的地方。最近我发现glibc++的一些内存池相当好用,内存分配原理也相当优秀。
大家都用过哪些内存池?
...全文
5849 62 打赏 收藏 转发到动态 举报
写回复
用AI写文章
62 条回复
切换为时间正序
请发表友善的回复…
发表回复
chenlizhibeing 2014-07-29
  • 打赏
  • 举报
回复
const dword sizeAffordable = 1 << 12; const dword sizeStandard = 1 << 16; extern struct memory: array<byte> { memory(); ~memory(); ::map<dword, array<void*> > map; vector<void*> stk; #ifdef _DEBUG dword szBytes; void uninitialize(); #endif // _DEBUG void *malloc(dword sz); } memHandler; void std::operator delete (void *p, dword sz) { if (!sz) return; #ifdef _DEBUG array<void*> &v = memHandler.map[sz]; for (dword i = 0; i < v.size; ++i) { if (p == v[i]) { throw; } } v.push_back(p); #else memHandler.map[sz].push_back(p); #endif } void *std::operator new (dword sz) { if (!sz) return 0; dword mid; void *p; if (memHandler.map.binary_search(sz, mid)) { auto &v = memHandler.map.ptr[mid].y; if (!!v) { v.pop_back(p); return p; } } p = memHandler.malloc(sz); return p; } #ifdef _DEBUG void memory::uninitialize() { szBytes += capacity - size; asm_stosb(ptr, 0xcc, size); } #endif void *memory::malloc(dword sz) { if (size < sz) { #ifdef _DEBUG uninitialize(); #endif // _DEBUG dword sizeAllocated; if (sz <= sizeAffordable) sizeAllocated = sizeStandard; else sizeAllocated = asm_pow2(sz) << 4; void *ptr = this->ptr; this->ptr = (byte*)::malloc(sizeAllocated); assert (this->ptr); capacity = size = sizeAllocated; stk.push_back(ptr); } size -= sz; return ptr + size; } memory::memory() { ptr = (byte*)::malloc(sizeStandard); capacity = size = sizeStandard; #ifdef _DEBUG szBytes = 0; #endif // _DEBUG } memory::~memory() { #ifdef _DEBUG uninitialize(); for (dword i = 0; i < map.size; ++i) { auto &p = map.ptr[i]; szBytes -= p.y.size * p.x; szBytes -= p.y.capacity << 2; for (dword i = 0; i < p.y.size; ++i) asm_stosb(p.y.ptr[i], 0xcc, p.x); asm_stosd(p.y.ptr, 0xcccccccc, p.y.capacity); } szBytes -= stk.capacity(stk.size) + map.capacity * sizeof (decltype(*map.ptr)); asm_stosb(stk.ptr, 0xcc, stk.capacity(stk.size)); asm_stosb(map.ptr, 0xcc, map.capacity * sizeof (decltype(*map.ptr))); for (dword i = 0; i < capacity / 4; ++i) if (((dword*)ptr)[i] != 0xcccccccc) { throw; } if (szBytes) { throw; } #endif // _DEBUG for (dword i = 0; i < stk.size; ++i) ::free(stk[i]); ::free (ptr); clear(); map.clear(); stk.clear(); } 一种内存池实现的方法
渔村居士 2013-09-30
  • 打赏
  • 举报
回复
收藏了!~~~
xiaolomg 2013-01-21
  • 打赏
  • 举报
回复
看了楼上的各种暴强回复,我决定好好看看内存池实现了
蜗牛的信仰 2012-07-04
  • 打赏
  • 举报
回复
修行,内功尚浅,无法分析.
hkey2251 2012-07-04
  • 打赏
  • 举报
回复
回帖已经这么多了,不知道楼主能不能看到,

使用内存池就是减少频繁malloc/free时的效率和减少碎片;

还有内存泄露,

从堆上malloc一块内存当做内存池使用,管理它,和对裸堆进行内存管理是一样的,

动态管理,见过比较好的是slab分配器,

实现原理、源代码搜下,很多




reezonew 2012-07-04
  • 打赏
  • 举报
回复
“为了代码而效率,而是为了效率而代码”
说得好!现在的效率瓶颈是人,不是机器。
叶小然 2012-07-02
  • 打赏
  • 举报
回复
很热闹。一山不容二虎。针锋相对的,其实也没有必要,一起讨论而已。
icenic 2012-07-02
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

又不是什么高级技术, 实现方法都一样.

把握一个概念:

内存池就是内存, 内存管理器才是操作内存池的接口, 你要实现的是内存管理器, 不是内存池, 内存池malloc上几百兆就叫做内存池了。
[/Quote]
内存池和内存管理器的关系类似于数据库和数据管理系统的关系,话是没有错,但没必要纠结于这些文字细节。不同内存池的内存分配算法和内存池数据组织方式还是会有差别的。
scgywx 2012-07-02
  • 打赏
  • 举报
回复
我插,打错了
tcmalloc
jemalloc..
scgywx 2012-07-02
  • 打赏
  • 举报
回复
tcmall和jemall算吗?
haha_ 2012-07-02
  • 打赏
  • 举报
回复
如果只从内存上讲,你自己实现的还真不一定有stl实现的好,因为stl是allocate就是参数校验,然后直接调用操作系统的api.你不使用stl所节省的时间,就是少调用那些系统api的时间. 所以肯定要申请份大内存,然后自己管理呗.
我看了楼主的帖子,应该是string,vector这些stl影响效率? 其实这些都可以使用栈重新实现的,如果使用栈,你得知道string,vector的最长大小是多少,当成模版参数传进去就OK了.甚至可以设置成长度超过一定大小就使用堆,小于一定大小就使用栈.这些工作量都不大.

最后,栈的大小不仅可以通过编译器设置,还可以在程序中动态修改,简单的来说,修改esp就可以了,复杂点修改线程环境,一劳永逸.所以栈大小也不存在问题。
小新小小新 2012-06-30
  • 打赏
  • 举报
回复
功力不到,很多看不懂
dtgdf2006 2012-06-30
  • 打赏
  • 举报
回复
我还是感谢大家提供这么多的意见,虽然优秀的pool不少,但我觉得对可靠性要求比较高的话,像madmanahong说的多使用栈少用STL是最靠谱的方法。
可见一斑 2012-06-30
  • 打赏
  • 举报
回复
[Quote=引用 34 楼 的回复:]
http://www.lutiaotiao.com/main/title/66/
供参考
[/Quote]

这篇文章分析的比较透彻,但作者忽略了非常重要的一点,那个所谓的128限制其实是可以自己调整的,
我个人就是把他调整为分页大小-1。
可见一斑 2012-06-30
  • 打赏
  • 举报
回复
[Quote=引用 41 楼 的回复:]
使用 intel TBB

还有ipp,mkl, 等众多高性能的模板,库。。。

稳定,性能卓越超群。
[/Quote]

貌似靠谱一些,但intel的价格不菲啊。
可见一斑 2012-06-30
  • 打赏
  • 举报
回复
[Quote=引用 43 楼 的回复:]
确实没啥好讨论的,用途不一样,策略就不一样。Flase sharing是一个应该避免的问题。

论文很多。38楼的测试只是单线程下,确实没有啥优势。

想做到scalable的memory pool,确实需要一定的技巧,

另外 Maged M. Michael 的论文还是别看了,我看过,那个在实验室可以,用在工程中的话,除非你是一个单独做内存池系统的人,而且公司给你1年时间制作,否则……
[/Quote]


我记住了,
不过我之前说过的那个mt_alloc确实可以很好的解决你所说的问题,就当是我推荐的吧,没别的意思。
关于boost::pool_allocator我用了不止一次,也确实可以带来一些不错的效果,但可能是我的水平过于有限,也可能是平台的问题,在单线程下仍然成为了性能瓶颈,所以不敢用了。
lu_zi 2012-06-29
  • 打赏
  • 举报
回复
http://www.lutiaotiao.com/main/title/66/
供参考
lu_zi 2012-06-29
  • 打赏
  • 举报
回复
http://www.lutiaotiao.com/main/title/66/
供参考
qingcairousi 2012-06-29
  • 打赏
  • 举报
回复
Scalable Lock-Free Dynamic Memory Allocation
Maged M. Michael
IBM Thomas J. Watson Research Center
P.O. Box 218, Yorktown Heights, NY 10598, USA
magedm@us.ibm.com

无锁allocator的实现
hslinux 2012-06-29
  • 打赏
  • 举报
回复


在我的理解里面,
内存池对于使用者来说,就是一种内存分配方式,与基础库的new,delete类似。

对于内存池的实现者来说,就是利用基础库的New,delete再实现一个大块的内存管理类。

也许个人比较懒散,或者说得好听的就是比较实际:
很多编码这玩意的好坏,没有一个绝对的标准,能用最简单方式比较高效的满足项目需求,个人认为就是很效率了。
内存池这玩意也一样,要复杂可以搞得很复杂,要简单也可以搞得很简单,能满足项目需要就可以了。

下面有三个内存池,有兴趣的可以研究下:

google的开源项目:google-perftools
http://code.google.com/p/google-perftools/

A Memory Allocator
http://g.oswego.edu/dl/html/malloc.html
多平台,代码量不大,应用广泛,但是不是线程安全的。

基于“A Memory Allocator ”编写的线程安全的内存池:nedmalloc
http://www.nedprod.com/programs/portable/nedmalloc/
http://sourceforge.net/projects/nedmalloc/files/latest/download

加载更多回复(36)

64,282

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧