内存池的简单试验(C++)

类别:编程语言 点击:0 评论:0 推荐:

这是试验性的程序, 虽然算法实现简弱, 当在编译器优化后实验结果,
性能比用全局new delete的内存管理好了很多,我这里有考虑到多线程
看来在大量使用内存分配的程序,用内存池是能够显著提高性能的;
有时间我会改进算法,有高手看到, 请指点一二, 我是非专业的, 算法方面很弱;

还有数组的内存分配遇到了一些问题;
以下数组的内存分配的一般模式

void * operator new[](size_t size);
void operator delete[](void *p, size_t size);

可惜的是new里的size和delete你的size在vc, bc下并不匹配(g++则一样, 比较好);
这是的分配数组是需要保存指针及对应的大小(一般用hash), 这要消耗不少时间;

#pragma warning(disable: 4530)
#pragma warning(disable: 4786)
#include <map>
#include <cassert>
#include <iostream>
#include <algorithm>
#include <exception>
#include <iomanip>
#include <list>
using namespace std;

#include <windows.h>

template<size_t PreAllocSize = 1024> 
class MemoryPool
{
protected:

 struct MemoryBlock
 {
  char *_Address;
  size_t _Size;
  MemoryBlock * _Next;
  MemoryBlock(void *pbegin, size_t size) : _Address((char *)pbegin), _Size(size), _Next(NULL) { };
 };

 struct Lock
 {
  CRITICAL_SECTION &CS;
  Lock(CRITICAL_SECTION &cs) : CS(cs)  {  EnterCriticalSection(&CS);  }
  ~Lock()         {  LeaveCriticalSection(&CS);  }
 };

 char _Buffer[PreAllocSize];
 char *_Begin, *_End;
 CRITICAL_SECTION _csLock;
 list<MemoryBlock * > _MemoryList;


 void CreateList()
 {
  _MemoryList.push_back(new MemoryBlock(_Begin, PreAllocSize));
 }

 void FreeList()
 {
  list< MemoryPool::MemoryBlock * >::iterator iter;

  for(iter = _MemoryList.begin(); iter != _MemoryList.end(); iter ++)
   delete (*iter);

  _MemoryList.clear();
 }

 void *FFA_Alloc(size_t size)// First fit algorithm
 {
  char *p = NULL;
  list< MemoryPool::MemoryBlock * >::iterator iter;

  for(iter = _MemoryList.begin(); iter != _MemoryList.end(); iter ++)
  {
   if(size < (*iter)->_Size)
   {
    p = (*iter)->_Address, (*iter)->_Address += size, (*iter)->_Size -= size;
    break;
   }
   else
   {
    if(size == (*iter)->_Size)
    {
     p = (*iter)->_Address;
     delete (*iter);
     _MemoryList.erase(iter);
     break;
    }
   }
  }

  return p;
 }

 bool FFA_Free(char *p, size_t size)
 {
  if(p < _Begin || p + size > _End)
   return false;

  list< MemoryPool::MemoryBlock * >::iterator iter, temp_iter;

  for(iter = _MemoryList.begin(); iter != _MemoryList.end(); iter ++)
  {
   if(p < (*iter)->_Address)  //find the insert point
   {
    if(p + size > (*iter)->_Address)//error
     return false;

    if(iter == _MemoryList.begin())
    {
     if(p + size == (*iter)->_Address) //union next_node
      (*iter)->_Address = p, (*iter)->_Size += size;
     else  //insert
      _MemoryList.insert(iter, new MemoryBlock(p, size));
    }
    else
    {
     temp_iter = iter, temp_iter--; //get pre_node

     if((*temp_iter)->_Size + (*temp_iter)->_Address == p) //must union pre_node
     {
      if(p + size == (*iter)->_Address)//union next_node and pre_node
      {
       (*temp_iter)->_Size += size + (*iter)->_Size ;
       _MemoryList.erase(iter);
      }
      else  //just union pre_node
       (*temp_iter)->_Size += size;
     }
     else
     {
      if(p + size == (*iter)->_Address)//union next_node
       (*iter)->_Size += size,  (*iter)->_Address = p;
      else
       _MemoryList.insert(iter, new MemoryBlock(p, size));
     }
    }
    return true;
   }//  if(p < (*iter)->_Begin)
  }  //for

  if(_MemoryList.size() == 0) // null list
   _MemoryList.insert(_MemoryList.end(), new MemoryBlock(p, size));
  else  //push back of list
  {
   list< MemoryPool::MemoryBlock * >::reverse_iterator r_iter = _MemoryList.rbegin();

   if((*r_iter)->_Size + (*r_iter)->_Address == p) //must union pre_node
    (*r_iter)->_Size += size;
   else
    _MemoryList.insert(_MemoryList.end(), new MemoryBlock(p, size));  
  }

  return true;
 }

 void *BFA_Alloc(size_t size)// Best fit algorithm
 {
 }

 bool BFA_Free(char *p, size_t size)
 {
 }

 void *WFA_Alloc(size_t size)// Worst fit algorithm
 {
 }

 bool WFA_Free(char *p, size_t size)
 {
 }
 

public:

 MemoryPool()// : _MemoryHash(PreAllocSize / 16)
 {
  _Begin = _Buffer, _End = _Buffer + PreAllocSize;
  InitializeCriticalSection(&_csLock);
  CreateList();
 }

 ~MemoryPool()
 {
  DeleteCriticalSection(&_csLock);
  FreeList();
 }

 void *Alloc(size_t size)
 {
  Lock lock(_csLock);

  void *p = FFA_Alloc(size);

  return p ? p : malloc(size);
 }

 void Free(void *address, int size)
 {
  Lock lock(_csLock);

  if(!size)
   size = 1;

  if(!FFA_Free((char *)address, size))
  {
   printf("\nfree error : address %p size %d\n", address, size);
   free(address);
  }
 }

 void PrintList()
 {
  printf("\n");
  int i;

  if(_MemoryList.size() == 0)
  {
   printf("no memory!\n");
   return;
  }

  list< MemoryPool::MemoryBlock * >::iterator iter;
  for(i = 0, iter = _MemoryList.begin(); iter != _MemoryList.end(); iter ++, i ++)
   printf("%d : Address %p offset %d, size %d;\n",
    i, (*iter)->_Address, (*iter)->_Address - _Begin, (*iter)->_Size);
 }
};

class Object
{
public:

 static MemoryPool<2 * 1024 * 1024> _MP;

 void * operator new (size_t size)
 {
  return _MP.Alloc(size);
 };
 
 void operator delete(void * p, size_t size)
 {
  _MP.Free(p, size);
 };
};

MemoryPool<2 * 1024 * 1024> Object::_MP;

int main(int argc, char* argv[])
{
 
 int i;
 Object **x = new Object *[1000000];

 int bt = GetTickCount();

 for(i = 0 ; i < 1000000; i++)
  x[i] = new Object();

 for( i = 0 ; i < 1000000; i++)
  delete x[i];
 
 cout << "使用内存池 " << GetTickCount() - bt << endl;


 bt = GetTickCount();

 for(i = 0 ; i < 1000000; i++)
  x[i] = ::new Object[10];

 for( i = 0 ; i < 1000000; i++)
  ::delete x[i];
 
 cout << "使用全局NEW " << GetTickCount() - bt << endl;

 return 0;
}

 

本文地址:http://com.8s8s.com/it/it24631.htm