C++内存管理
来源:互联网 发布:java基础语法总结 编辑:程序博客网 时间:2024/06/05 00:29
C++内存池初探
原创文章,转载请注明出处:http://blog.csdn.net/fastsort/article/details/12356369
///mymem.h 使用自己定义的内存管理需要包含这个头文件
#ifndef__mymem_h__#define__mymem_h__template<classT>classCachedObj{public:void*operator new(std::size_t);voidoperator delete(void *, std::size_t);virtual~CachedObj(){}protected:T* next;private:staticvoidAddToFreeList(T *);staticstd::allocator<T>allocMem;staticT *freeStore;staticconststd::size_tchunk;};/////////////////////////////////////////////////////////函数实现和数据初始化///模板中将头文件和实现文件分离在vs中有问题//////////////////////////////////////////////////////template<classT>void*CachedObj<T>::operator new(size_t sz){//cout<<"op new"<<endl;if(sz != sizeof(T))///在vs下这里没问题,在Linux下这里需要修改一下throwstd::runtime_error("CachedObj : wrong size object in op new. ");if(!freeStore){T * a = allocMem.allocate(chunk);for(size_t i=0; i!= chunk; i++)AddToFreeList(&a[i]);}T* p = freeStore;freeStore = freeStore->CachedObj<T>::next;return p;}template<class T>voidCachedObj<T>::operator delete(void *p, size_t sz){//cout<<"op delete"<<endl;if(p)AddToFreeList(static_cast<T*>(p));}template<class T>voidCachedObj<T>::AddToFreeList(T * p){p->CachedObj<T>::next = freeStore;freeStore = p;}template<class T>std::allocator< T >CachedObj<T>::allocMem ;template<class T>T *CachedObj<T>::freeStore = 0;template<class T>constsize_tCachedObj<T>::chunk = 20 ;#endif //#endif __mymem_h__
由于使用了模板,如果把头文件和实现代码分离,编译出错。
在网上也查询了一些解决办法,但是都有局限性,不同编译器的支持度也不一样,所以干脆实现代码也放在头文件里了。
//// main.cpp 测试用的主函数
#include<iostream>#include<time.h>#include<fstream>#include"mymem.h"///自己定义的内存管理基类usingnamespacestd;ofstreamofs("perfRec.txt",ios::app);/***优化S类的内存管理 **/classS:publicCachedObj<S>{public:S(){}voidfun(){cout<<"fun is called!"<<endl;}~S(){}};/**不优化T的内存管理**/classT{public:T(){}voidfun(){cout<<"fun is called!"<<endl;}~T(){}};/**记录测试结果的函数**/voidrec(intcnt, int sd, int td){ofs<<cnt<<"\t\t";///countofs<<sd<<"\t\t"<<td<<"\t\t";//s , dif(sd)ofs<< ((int)(1.0*td/sd*10)/10.0) <<endl;///加速比,保留一位小数elseofs<< "-" <<endl;ofs.flush();}/**申请完立即释放测试**/voidtestA(int n=1024000){cout<< __FUNCTION__ <<" count = "<< n <<endl;//intCTest = n;clock_tstart,end;start = clock();for(int i=0; i<n; i++){S*ps = newS();deleteps;}end = clock();intsd = end-start;cout<<"S duratuon : "<< sd <<"ms"<<endl;start = clock();for(int i=0; i<n; i++){T*ps = newT();deleteps;}end = clock();int td = end-start;cout<<"T duration : "<< td <<"ms"<<endl;rec(n,sd,td);}/**申请完不立即释放测试***/voidtestB(int n=1024000){cout<< __FUNCTION__ <<" count = "<< n <<endl;S** psa = new S*[n] ;clock_tstart,end;start = clock();for(int i=0; i<n; i++){psa[i] = new S();}for(int i=n-1; i>=0; i--){delete psa[i];}end = clock();intsd = end-start;cout<<"S duratuon : "<< sd <<"ms"<<endl;T** pta = new T*[n];start = clock();for(int i=0; i<n; i++){pta[i] = new T();}for(int i=n-1; i>=0; i--){delete pta[i];}end = clock();int td = end-start;cout<<"T duration : "<< td <<"ms"<<endl;rec(n,sd,td);delete[]psa;delete[]pta;}voidfa(int n){int i,s;ofs<<"===================Table a==================="<<endl;ofs<<"!!! release after per alloc at once !!!"<<endl;ofs<<"count"<<"\t\t"<<"s duration(ms)"<<"\t\t"<<"t duration(ms)"<<endl;for(i=0,s=1000; i<n; i++){s *= 10;testA(s);}//testA(s*5);}voidfb(int n){int i,s;ofs<<"===================Table B==================="<<endl;ofs<<"!!! release after alloc all elements !!!"<<endl;ofs<<"count"<<"\t\t"<<"s duration(ms)"<<"\t\t"<<"t duration(ms)"<<endl;for(i=0,s=1000; i<n; i++){s *= 10;testB(s);}//testB(s*5);}intmain(){ofs<<"========performance test in win7(x64)========"<<endl;int n=4;int cnt=10;while(cnt--){fa(n);fb(n);}ofs<<"======test end=========\n\n\n\n\n\n\n"<<endl;return 0;}
如果要对某个类进行手动内存管理(或者说用我们自己定义的内存池),只需要让该类继承CachedObj类即可。
需要注意的是,CachedObj是一个模板,继承应该这样写:
class S:publicCachedObj<S>{...};
为了对比,同时定义了另外一个类T,使用系统的内存管理策略。
测试结果:
(第一列为申请/释放内存次数,第二列为S的结果,第三列为T的结果,最后一列是T/S的值)
在win7(x64)下:
===================Table a===================!!! release after per alloc at once !!!counts duration(ms)t duration(ms)1000001-10000011010100000089612100000007197713.7===================Table B===================!!! release after alloc all elements !!!counts duration(ms)t duration(ms)1000001-10000021261000000121159.51000000012311859.6效果十分明显,效率提升约十倍!
但是代码放到Linux下,就不是那么明显了:
========performance test in ubuntu ===========================Table a===================!!! release after per alloc at once !!!counts duration(m)t duration(ms)1000000-10000010000100001100000050000600001.210000000530000560000150000000264000028600001===================Table B===================!!! release after alloc all elements !!!counts duration(m)t duration(ms)1000000-10000010000100001100000070000800001.1100000006700008300001.250000000325000041300001.2
不得不说,Linux比win的内存管理貌似牛x很多。
继续测试,将chunk修改为每次增大一倍,直到不能增大,但是效果还是不明显,仍然在1附近。
后来无意中想起优化选项,
于是编译时添加-O0和-O3,对比其结果有什么不同。
开始很奇怪的是,-O3不仅没有提高效率,反而降低了效率。
但是后来分析发现,只是加速比增加的很明显,而实际上,绝对速度都比未优化的要快:
使用-O0和-O3优化选项的结果对比图。
由此看出,使用自己的内存池管理内存还是有必要的。
遗留问题:
申请的内存始终没有返回给系统。
如果系统出现某个很高的峰值后,一直处在较低的负载下运行,则有大量的内存被本程序占用且未被使用。
一个解决办法是每隔一段时间,看内存池空闲的的比例是多少,如果很高,则释放一部分返回给系统。
附:整个测试代码和结果
http://download.csdn.net/detail/hello_world_2012/6360453
参考:《C++ primer 第四版》
原创文章,转载请注明出处: blog.csdn.net/fastsort/article/details/12356369
- C/C++ 内存管理
- C内存管理函数
- C内存管理
- C内存管理
- object c 内存管理
- C 内存管理详解
- C 内存管理
- C语言内存管理
- c/c++内存管理
- c 的内存管理
- C内存管理
- Ojbective-c 内存管理
- C内存管理
- objective-c内存管理
- Objective-c 内存管理
- Objective-C内存管理~~
- c,c++内存管理
- Objective-C内存管理
- 高度
- 分段与分页
- 编程之美-程序理解和时间分析
- volatile
- 百度——个人云存储pcs——Android使用百度云盘(2)——创建文件夹和上传文件
- C++内存管理
- C++四种强制转型
- javascript 创建对象的几种方式
- 自定义TabHost,TabWidget样式 .
- 70道经典Android面试题加答案
- GridView 中的日期以一定格式显示
- 理财
- Java使用jxl操作Excel
- HDU 4294 Multiple【BFS】