您的位置:首页 > 编程语言 > C语言/C++

efficient c++,单线程内存池

2015-06-05 17:07 477 查看
基于 /article/6746125.html operator new的知识基础上 介绍这个章节的内容

对于一般直接 new 与delete 性能较差,可以自己管理写内存的申请与释放。其实一般的operator new 和operator delete 直接调用 malloc 和 free的。

版本0:

class Rational
{
public:
Rational(int a=0, int b =1 ): n(a),d(b){}
private:
int n;
int d;
};


版本1:专用的内存管理器

#include <stddef.h> // for size_t
#include <iostream>

using namespace std;

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; // A free list of Rational objects.
static void expandTheFreeList();
enum { EXPANSION_SIZE = 32};

int n; // Numerator
int d; // Denominator
};

inline
void * Rational::operator new(size_t size)
{
if (0 == freeList) {// If the list is empty, fill it up.
expandTheFreeList();
}

NextOnFreeList *head = freeList;
freeList = head->next;

return head;
}

inline
void Rational::operator delete(void *doomed, size_t size)
{
NextOnFreeList *head = static_cast <NextOnFreeList *> (doomed);
head->next = freeList;
freeList = head;
}

void Rational::expandTheFreeList()
{
// We must allocate an object large enough to contain the next
// pointer.
size_t size = (sizeof(Rational) > sizeof(NextOnFreeList *)) ?
sizeof(Rational) : sizeof(NextOnFreeList *);

//    NextOnFreeList *runner = static_cast <NextOnFreeList *>(new char[size]);
NextOnFreeList *runner = (NextOnFreeList *)(new char[size]);

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

runner->next = 0;

cout << "expand" << endl;
}

void Rational::deleteMemPool()
{
NextOnFreeList *nextPtr;
for (nextPtr = freeList; nextPtr != NULL; nextPtr = freeList) {
freeList = freeList->next;
delete [] nextPtr;
}
}
//测试code

NextOnFreeList *Rational::freeList = 0;

int main()
{
Rational *array[1000];

Rational::newMemPool();

// Start timing here

for (int j = 0; j < 500; j++) {
for (int i = 0; i < 1000; i++) {
array[i] = new Rational(i);
}
for (int i = 0; i < 1000; i++) {
delete array[i];
}
}

// Stop timing here

Rational::deleteMemPool();

return 0;
}


这版本是通过重载 目标类 中的new 与delete 实现内存管理,只适用于目标类,但是速度是最快的。

实现方式是维护一个链表,类中静态声明链表头,链表维护一串空间,通过类型转换在 目标类 和 链表指针 之间转换。

如果内存不够(freelist=NULL)是一次申请较多内存进行维护。

链表的添加删除(对于函数释放空间与申请空间)是在链首操作。

书上47 行 52行通过 静态类型转换不成功,改为了 强制转换,在 g++ 中能够编译运行。

主要在主函数中调用静态函数 链表的申请与释放。

版本2:固定大小对象的内存池

考虑版本1,可以通过模板实现管理特定的对象。最主要的参数是类的大小。

实现是专门声明一个管理内存的内存池类,使用模板实现,提供alloc() free() 接口,给类申请与释放内存。

内存池类的实现是自身有一个MemoryPool<T>* next 指针用来指向维护的链表,内存的操作都在链首位置。

#include <stddef.h>
#include <iostream>

using namespace std;

template <class T>
class MemoryPool {
public:
MemoryPool (size_t size = EXPANSION_SIZE);
~MemoryPool ();

// Allocate a T element from the free list.
inline void* alloc (size_t size);

// Return a T element to the free list.
inline void free (void *someElement);
private:
// next element on the free list.
MemoryPool<T> *next;

// If the freeList is empty, expand it by this amount.
enum { EXPANSION_SIZE = 32};

// Add free elements to the free list
void expandTheFreeList(int howMany = EXPANSION_SIZE);
};

template <class T>
MemoryPool <T> :: MemoryPool (size_t size)
{
expandTheFreeList(size);
}

template < class T >
MemoryPool < T > :: ~MemoryPool ()
{
MemoryPool<T> *nextPtr = next;
for (nextPtr = next; nextPtr != NULL; nextPtr = next) {
next = next->next;
cout << nextPtr << endl;
//delete [] nextPtr;
//delete  nextPtr;
delete [](char*)nextPtr;  //不太明白为什么这样是对的,上面的方法不行。。
                    //明白了,因为new的时候就是用char字节的方法申请的,delete的时候要对应。。

}
}

template < class T >
inline
void* MemoryPool < T > :: alloc (size_t)
{
if (!next) {
expandTheFreeList();
}

MemoryPool<T> *head = next;
next = head->next;

return head;
}

template < class T >
inline
void MemoryPool < T > :: free (void *doomed)
{
MemoryPool<T> *head = static_cast <MemoryPool<T> *> (doomed);

head->next = next;
next = head;
}

template < class T >
void MemoryPool < T > :: expandTheFreeList(int howMany)
{
// We must allocate an object large enough to contain the
// next pointer.
size_t size = (sizeof(T) > sizeof(MemoryPool<T> *)) ?
sizeof(T) : sizeof(MemoryPool<T> *);

//MemoryPool<T> *runner = static_cast <MemoryPool<T> *>(new char [size]);
MemoryPool<T> *runner = (MemoryPool<T> *)(new char [size]);

next = runner;
for (int i = 0; i < howMany ; i++) {
//runner->next = static_cast <MemoryPool<T> *> new char [size];
runner->next = (MemoryPool<T> *)( new char [size]);
runner = runner->next;
}
runner->next = NULL;
}

class Rational {
public:
Rational (int a = 0, int b = 1 ) : n(a), d(b) {}

void *operator new(size_t size) { return memPool->alloc(size); }
void operator delete(void *doomed,size_t size)
{ memPool->free(doomed); }

static void newMemPool() { memPool = new MemoryPool <Rational>; }
static void deleteMemPool() { delete memPool; }
private:
int n; // Numerator
int d; // Denominator

static MemoryPool <Rational> *memPool;
};

MemoryPool <Rational> *Rational::memPool = 0;

int main()
{
Rational *array[1000];

Rational::newMemPool();

// Start timing here

for (int j = 0; j < 500; j++) {
for (int i = 0; i < 1000; i++) {
array[i] = new Rational(i);
}
for (int i = 0; i < 1000; i++) {
delete array[i];
}
}

// Stop timing here

Rational::deleteMemPool();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: