荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: mmkiller (8楼电梯里的6个傻男人), 信区: Program
标  题: Memory Pool 技术
发信站: 荔园晨风BBS站 (2005年11月02日23:18:01 星期三), 站内信件


http://www.blog.edu.cn/user2/55120/archives/2005/351841.shtml#183165

C++内存池实现(1)前言
本文是“C++内存池实现”的第一部分,本文内容来自《提高C++性能的编程技术》,我只
是对里面的内容进行了整理,并对一些晦涩的地方进行了解释。

对原书中的一些代码进行了调整,使之在VS.NET 2003的环境下调试通过。

全局函数new()和delete()
       C++默认的new()和delete()方式是通用的内存管理方式,可以通过此分配和释放大
小不同的内存,在多线程的环境中,提供了对内存分配和释放的并发保护,但是这些灵活
性是以牺牲性能、程序的执行速度为代价的。让我们看一个例子:



       首先是我们要操作的有理数类的定义rational.h:



//

// rational.h – definition of the rational class

// wangzhi 2005-10-25

//

#ifndef _RATIONAL_H

#define _RATIONAL_H



class Rational

{

public:

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



private:

    int n;     // Numerator

    int d;     // Denominator

};



#endif // _RATIONAL_H



    接下来是测试程序的代码test1.cpp:



//

// test1.cpp – test the global new() and delete() functions’ performance

// wangzhi 2005-10-25

//

#i nclude <windows.h>

#i nclude <stdio.h>

#i nclude "rational.h"



int main()

{

    Rational *array[1000];



    // Start timing here

    DWORD last, current;

    last = GetTickCount();



    for (int j = 0; j < 500; j ++)

    {

       for (int i = 0; i < 1000; i ++)

           array[i] = new Rational(i);



       for (i = 0; i < 1000; i ++)

           delete array[i];

    }



    // Stop timing here

    current = GetTickCount();



    printf("Time cost: %d", current - last);

    getchar();

}



程序的运行结果是:



Time cost: 7281ms


专用Rational内存管理器
在大多数的C++程序中,我们可能只需要分配和释放一些大小固定的内存空间,而且程序可
能只会在单线程的环境中运行,因此如果此时使用功能强大的new()和delete()就会导致很
大的性能开销,在此我们实现一个上述定义的Rational类的对象静态链表,这个静态列表
将作为一个可用对象的空闲列表,需要Rational对象时就从空闲列表中取出一个,对象操
作完毕后,再将它放回空闲列表中。如图1示:




图1 Rational对象的空闲列表



       接下来看看头文件rational1.h的定义:



//

// rational1.h - definition of the NextOnFreeList and rational class

// wangzhi 2005-10-25

//

#ifndef _RATIONAL1_H

#define _RATIONAL1_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;

};



#endif // _RATIONAL1_H



    在rational1.h中首先定义了一个辅助类NextOnFreeList用以链接不同的Rational对象
,需要注意的是,空闲列表的每一个元素既是NextOnFreeList对象,又是Rational对象,
每个Ratioanl对象的头几个字节是一个NextOnFreeList指针,指向空闲列表中下一个Ratio
nal对象。

       现在来看一下专用Rational内存池的实现rational1.cpp:



//

// rational1.cpp – implement the Rational specific memory pool

// wangzhi 2005-10-25

//

#i nclude "rational1.h"



void *Rational::operator new (size_t size)

{

    if (0 == freeList)

       expandTheFreeList();



    NextOnFreeList *head = freeList;

    freeList = head->next;

    return head;

}



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 *);

    NextOnFreeList *runner = reinterpret_cast<NextOnFreeList *>

(new char[size]);

    freeList = runner;

    for (int i = 0; i < EXPANSION_SIZE; i ++ )

    {

       runner->next = reinterpret_cast<NextOnFreeList *> (new char[size]);

       runner = runner->next;

    }



    runner->next = 0;

}



void Rational::deleteMemPool()

{

    NextOnFreeList *nextPtr;

    for ( nextPtr = freeList; nextPtr != 0; nextPtr = freeList )

    {

       freeList = freeList->next;

       delete[] nextPtr;

    }

}



    程序首先重载了new()和delete()以实现Rational类特有的内存管理方式,new()从空
闲列表中分配一个新的Rational对象,如果列表为空,则扩展它,在这里是从列表的头部
取一个新对象返回,然后将空闲列表头部指针freeList后移。delete()将一个使用过的Rat
ional对象返回空闲列表,将它插入空闲列表的头部,此时的freeList指针将指向它。

    当需要分配一个新对象,而空闲列表已使用完时,需要调用expandTheFreeList()从堆
中分配更多的Rational对象以备用。这里先说明下一个要点,就是当分配一个对象内存时
,该对象内存的头几个字节被强制转换为NextOnFreeList*类型,以便插入到空闲列表中,
当程序使用new()将该对象内存从空闲列表取出时,原来NextOnFreeList*指针占有的空间
将被使用,当程序使用完此对象并用delete()将其返回空闲列表时,对象的头几个字节又
被转换为NextOnFreeList*指针类型,然后对象链接入空闲列表中,在expandTheFreeList(
)中,由于一个对象内存需要包含NextOnFreeList*指针和Rational对象,所以需要分配一
个足够大的内存空间,然后将此内存空间的开始几个字节强制转换为NextOnFreeList*类型
,并使freeList指向此内存空间,然后依次分配EXPANSION_SIZE个对象内存。

    deleteMemPool()用于释放整个内存池,该函数遍历整个空闲列表,删除每个对象内存
空间,注意在分配内存时使用了new char[size],因此在删除时就要使用delete[]
nextPtr。



下面是测试程序test2.cpp:



//

// test2.cpp – test the Rational specific memory pool’s performance

// wangzhi 2005-10-25

//


#i nclude <windows.h>

#i nclude <stdio.h>



#i nclude "rational1.h"



NextOnFreeList *Rational::freeList = 0;



int main()

{

    Rational *array[1000];

    Rational::newMemPool();



    // Start timing here

    DWORD last, current;

    last = GetTickCount();



    for (int j = 0; j < 500; j ++)

    {

       for (int i = 0; i < 1000; i ++)

           array[i] = new Rational(i);



       for (i = 0; i < 1000; i ++)

           delete array[i];

    }



    // Stop timing here

    current = GetTickCount();

    Rational::deleteMemPool();



    printf("Time cost: %d", current - last);

    getchar();

}



    程序的输出结果是:



Time cost: 109ms



结论
对1000个Rational对象进行500次的分配和释放,结果表明,使用全局的new()和delete()
耗时7281ms,而专用Rational内存管理器只耗时109ms,比前者快了近67倍。



全局函数new()和delete()是通用的内存管理方式,其灵活并能在多线程环境中控制并发,
但是也因此付出了性能的代价,一个特定的C++程序可以使用特定的内存管理方式来实现内
存的分配和释放,而不需要为不必要的考虑付出代价。


参考书目
《提高C++性能的编程技术》(Efficient C++ Performance Programming Techniques)

Dov Bulka, David Mayhew, Addison Wesley 2002


--
*[0;3*┌─╮˙                   ╭ ╭╮╭╭─╮╭┬╮*BigcatNAT 透明代理 功能*
*├─┤│╭─╮╭─  ╭─╮-┼-│││├─┤  │  *自 动 过 滤 收 费 连 接*
*└─╯│╰─│╰─╯╰─╰ ╰ ╰╰╯╰  ╯  ╰  *简 化 软 件 代 理 设 置*
        *╰─╯          *0 5 年 3 月 最 新 2 . 0 测 试 版 发 布*
     * *详 细 功 能 说 明 及 软 件 下 载 , 请 连 接 至 下 面 的 地 址   *
        *http://www.flashszu.com/BigcatNAT*    *Powered by BiGcAt.NET     *
※ 修改:·mmkiller 於 11月02日23:20:52 修改本文·[FROM: 192.168.110.120]
※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.110.120]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店