内存池笔记

来源:互联网 发布:数控车床编程例题 编辑:程序博客网 时间:2024/06/16 03:23
在大量频繁的申请释放内存的情境中,如果能对分配方式作出轻微的改进,那么在大量重复的过程中积累下的节省时间也是相当可观。
在《提高c++性能的编程技术》这本书中,第六章对于该场景给出了一个内存池例子,现将其代码整理如下并统计出同未优化的仅仅使用new delete时候的耗费时间对比。
其基本思路是,在频繁分配固定大小内存时候,先建立一个内存池,在请求内存仅仅需要将请求的固定大小内存块从内存池中摘出来供程序使用,返回时也仅仅将固定大小内存块返回内存池。
相比new delete指令,此时对请求内存仅仅是调整内存池中的指针,速度要提升很多。 如最后测试结果,耗费时间比例在4:1。
// Mem_Pool.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
class NextOnFreeList{
public:
NextOnFreeList* next;
};
class Rational{
public:
Rational(int a = 0,int b = 1):n(a),d(b){}
inline void* operator new(size_t size);
inline void operator delete(void* doomed,size_t size);
static void newMemPool() {expandTheFreeList();}
static void deleteMemPool();
private:
static NextOnFreeList* freeList;
static void expandTheFreeList();
enum {EXPANSION_SIZE = 32};
int n;
int d;
};
//  每次分配内存时候 首先检测freelist是否为空,为空则说明内存池需要扩展
//  调用expandTheFreeList()
//  不为空则直接从内存池调出一个指定大小的块。
inline void* Rational::operator new(size_t size)
{
if(0 == freeList){
  expandTheFreeList();
}
NextOnFreeList* head = freeList;
freeList = head->next;
return head;
}
//    删除内存时候 仅仅是将该内存块重新插入freelist
inline void Rational::operator delete(void* doomed,size_t size)
{
NextOnFreeList* head = static_cast<NextOnFreeList*> (doomed);
head->next = freeList;
freeList = head;
}

// 内存池扩展 每次扩展指定限额
void Rational::expandTheFreeList()
{
size_t size = (sizeof(Rational) > sizeof(NextOnFreeList *)) ?
  sizeof(Rational) : sizeof(NextOnFreeList *);
void* p = new char [size];
NextOnFreeList *runner =
    static_cast <NextOnFreeList *> (p);

freeList = runner;
for (int i = 0; i < EXPANSION_SIZE; i++) {
  void* pp = new char [size];
  runner->next =
   static_cast <NextOnFreeList *>(pp) ;
  runner = runner->next;
}
runner->next = 0;
}

//  整个内存池的分配删除释放 此处才是真正的释放
void Rational::deleteMemPool()
{
NextOnFreeList *nextPtr;
for (nextPtr = freeList; nextPtr != NULL; nextPtr = freeList) {
  freeList = freeList->next;
  delete [] nextPtr;
}
}
NextOnFreeList *Rational::freeList = 0;
class RationalOrigin{
public:
RationalOrigin(int a = 0,int b = 1):n(a),d(b){}
private:
int n;
int d;
};
void TestOriginBuf()
{
RationalOrigin *array[1000];
DWORD tStart = GetTickCount();
for(int j = 0;j < 5000;j++)
{
  int i ;
  for( i = 0;i < 1000;i++)
  {
   array[i] = new RationalOrigin(i);
  }
  for(int i = 0;i < 1000;i++)
  {
   delete array[i];
  }
}

tStart = GetTickCount() - tStart;
printf("TestOriginBuf run time is %d \n",tStart);
}
void TestAdvBuf()
{
Rational *array[1000];
Rational::newMemPool();
DWORD tStart = GetTickCount();
for(int j = 0;j < 5000;j++)
{
  int i;
  for( i = 0;i < 1000;i++)
  {
   array[i] = new Rational(i);
  }
  for(i = 0;i < 1000;i++)
  {
   delete array[i];
  }
}
tStart = GetTickCount() - tStart;
Rational::deleteMemPool();
printf("TestAdvBuf run time is %d \n",tStart);
}
int _tmain(int argc, _TCHAR* argv[])
{
TestOriginBuf();
TestAdvBuf();
return 0;
}
/*
TestOriginBuf run time is 1981
TestAdvBuf run time is 421
请按任意键继续. . .
*/
原创粉丝点击