首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

怎么证明STL是否使用了内存池

2012-05-28 
如何证明STL是否使用了内存池?我写了如下代码,想证明STL是否使用了内存池。我理解:如果使用了内存池,就不会

如何证明STL是否使用了内存池?
我写了如下代码,想证明STL是否使用了内存池。
我理解:如果使用了内存池,就不会频繁的new、delete内存。
可是,有两个问题:
① MinGW 4.4下new的计数是7,delete的计数也是7:是否证明MinGW的STL没有使用内存池。
② VC10下跑时,陷入了递归调用new的怪圈,也就无法证明了。

注:不要让我看代码,看了一部分,头都大了,结果还没看明白啥。牛人,如何证明之?
谢谢!

C/C++ code
#include <iostream>#include <vector>#include <stdlib.h>using namespace std;void* operator new(size_t size){    static int cnt;    cout << "new: " << ++cnt << endl;    return ::malloc(size);}void operator delete(void* p){    static int cnt;    cout << "delete: " << ++cnt << endl;    ::free(p);}int main(){    vector<int> v1(1);    int* p1 = new int(10);    vector<int> v2(1);    int* p2 = new int(8);    vector<int> v3(1);    vector<int> v4(1);    vector<int> v5(1);    delete p1;    delete p2;    return 0;}


[解决办法]
n层之后 会发现new
[解决办法]
除非你在malloc里面加个static变量否则 你想用程序来证明有点不可能吧。
[解决办法]
把vector的allocator自己指定一下不就成了么?
[解决办法]
使用内存池,不过是不信任malloc和new对内存的分配,只相信自己的内存管理比它们牛X的行为。当每次所分配的内存都是固定大小或者不需要频繁删除内存的情况下,或许确实是比较容易做到比malloc更牛X,否则我相信绝大多数程序员所写的内存池都比malloc要垃圾。
stl不过是把内存申请到一块连续内存去(申请后有盈余),不够用了再重新申请一块连续的迁移过来,删除原来的,这种方式算不算内存池,就看LZ你怎么看待了。另外set、map、list这些东西在做了删除动作后,也无法保证原本的连续性。
最后,LZ那个call CmdTest!malloc (004099b0)中的004099b0不是指大小,而是malloc函数的地址。

[解决办法]
探讨
引用:
使用内存池,不过是不信任malloc和new对内存的分配,只相信自己的内存管理比它们牛X的行为。当每次所分配的内存都是固定大小或者不需要频繁删除内存的情况下,或许确实是比较容易做到比malloc更牛X,否则我相信绝大多数程序员所写的内存池都比malloc要垃圾。
stl不过是把内存申请到一块连续内存去(申请后有盈余),不够用了再重新申请一块连续的迁移过来,删除原来的,这种方式算不算内存池,就看LZ你怎么看待了。另外set、map、list这些东西在做了删除动作后,也无法保证原本的连续性。
最后,LZ那个call CmdTest!malloc (004099b0)中的004099b0不是指大小,而是malloc函数的地址。


谢谢,可是,如何解释我重载全局的new和delete后,导致的计数变化呢?

[解决办法]
只能说试探吧,因为每次从内存池分配的内存的大小一般和你实际需要的会大点,你可以每次要求的内存大一点点,看看你实际得到的内存大小是多少了.如果有几次实际所得到的内存大小相同的话就应该是从内存池分配的.
[解决办法]
用内存池的好处,我以为是不把整个进程的堆弄乱,乱也只是自己那一块。
另外,分配更加快速。

[解决办法]
想测试STL有没有用内存池,很简单.
你测试一下用std::allocator分配内存和用malloc分配内存的性能就知道了.
一般,如果用了内存池,在分配小对象时有比较大的性能优势.比如STLPort.
[解决办法]
头次不是讨论过了吗?我联系发了两个贴:
第一:VC2008,GCC源代码不是SGI 的源代码,他们差距比较明显,只是前两者简单的封装。
第二:SGI源代码小于128btypes的时候用内存池。
[解决办法]
为什么要关心stl的默认allocator是怎么实现的呢。
一般7*24的程序,必须自己接管allocator的。
[解决办法]
7*24的自己接管内存是为了尽可能的减少内存碎片吧。频繁的分配和释放导致碎片率到达系统分配不了连续内存的状态时,系统就崩了...
[解决办法]
回30楼,那个是SGI STL的源代码,是实现了内存池的,小于128btyes的。同
侯捷剖析的那个差不多。

VC2008 STL没有实现,也就是23楼。

实际上这很简单,比较一下文件就看出来了。


[解决办法]
探讨
因为内存池的实现:只是从一块很大的内存里分隔4byte给vector <int> v(1)使用。
但从测试数据看:显然不是。


[解决办法]

探讨
引用:
地球人都知道,STL容器内存的分配策略是一开始分配一块比当前需求略大的内存(这也算是内存池的一种使用吧)
当插入新元素的时候,发现现有的内存已经用完的时候才会delete然后重新new
你那代码连插入元素都没有插入,就来讨论内存池

如果这也叫内存池,那内存池的概念要重新定义了。
如果我频繁的定义vector <int>实例,却需要频繁的new/delete,那当然是没有使用内存池了。
因为内存池的实现:只是从一块很大的内存里分隔4byte给vector <int> v(1)使用。
但从测试数据看:显然不是。

[解决办法]
在windows平台
new/delete内部调用的是malloc/free.

而malloc/free是C runtime 库函数。微软在实现这两个库函数malloc/free的时候采用
先创建一个页面大小(4K)的heap, 然后在这个页面上进行分配。它没有在进程default heap上分配。它是一个可增长的heap,也就是说当4K不能满足要求时,再分配。
如果分配空间很小,那么打开LFH(Low-fragmentation Heap)开关,在LFH打开的情况下最小heap分配粒度是8字节(MSDN有陈述)。而在LFH关闭的情况下最小heap分配粒度是16字节(MSDN没有陈述, 但是MSDN官网上技术文章有陈述,我很怀疑这个数值)。LFH在自己申请的heap中维护自己的一个内存池。所以C runtime库维护了自己的一个内存池。

VS2005 STL 的作者是P.J Plauer
他完全没有使用内存池来自己管理内存,如string, wstring实现中,如果string的大小小于16字节(为什么是16字节?看上面),那么在栈上分配空间,如果大于16字节则在heap上分配空间,分配空间时,调用的是C runtime 库函数。而C runtime 库维护了自己的一个heap.效率上还是比较高。

SGI STL 采用的是自己管理自己的内存池,它采用一个链表,最小分配粒度也是8字节,详细见《STL源码剖析》,SGI STL维护的内存池和windows平台C runtime 库维护的内存池原理上是一样的。SGI STL设计的目标是跨平台。

实际上微软在内存管理方面做了很多文章。所以上层软件用不用内存池对性能影响不大。
[解决办法]
一般应用程序自己实现内存池是为了解决大量小对象频繁分配和释放引起堆碎片的问题。不管堆本身实现得如何高效,增加自己的内存池会将堆本身管理策略对上层调用者的效率影响降至最低,特别当软件持续运行相当长的时间后,堆本身是否仍能满足调用者的需要。增加内存池用最适合自身应用程序特点的策略来接管堆内存显然会带来良好的效果。
程序中有大量小对象需要从堆上分配时会给程序带来严重的效率冲击:因为理论上堆会被大量这些小对象切割成无数段,长时间运行后堆千疮百孔,一会增加后续分配的搜索时间,二会造成后续大对象的分配失败,虽然堆内存的数量可能是够的,但是因为地址不连续也不能满足要求,(对于这种情调内存池的使用基本上必然的)。长时间运行的服务器最能体会到这一点。效率影响还来自于页面以及对齐,使用内存池能将对象集中,一次申请大块内存,然后将相关的对象分布于其上,比遍地开花将对象分散于各处要高效得多。现在操作系统的内存使用方式主要是页式印射,集中能避免频繁的页面抖动。
例如:假如一个链表有100个结点,结点是在堆上分配的。遍历这个链表时,如果100个结点集中分配于同一页面,那么无疑是高效的。但是如果这100个结果分布在100个页面上,那OS在遍历的时候需要把100页面全部换入。FT。地址的分散访问能飚升进程的RSS值,降低物理内存的使用率。自己使用内存池能控制页面对齐,缓冲对齐。。。好处多多。。。
上面有人说只有对象大小固定的才适用内存池,显然有这个当然好了,但是不构成判定用不用内存池的条件,大小不同,可以尽量让它们相同。。

[解决办法]
要知道stl的容器是否使用了内存池策略的allocator,直接看源码里Alloc模板参数的默认值是什么,再看这个默认的allocator是否使用内存池策略。

例如,VSTS 2010里面:
<vector>
C/C++ code
template<class _Ty,    class _Ax = allocator<_Ty> >    class vector
[解决办法]
探讨
草...居然拿我来开刷.......
42楼才是牛人,让我最佩服的回复,你跟我一起仰视他吧

热点排行