new操作的性能问题

    new操作是我们常用的堆空间分配方法,可以说离了它,我们基本写不出可用的工程代码。可是一切内存问题却皆源于此:

    1、内存碎片化:有足够的内存,却申请不到整块的空间;

    2、性能低下:new操作是考虑到多线程安全的,因此,调用时增加的多线程安全的负担;在堆空间上分配内存时,进程要进行内核态切换,又增加了额外的开销;

    3、内存丢失:不用说,忘记delete的对象一直占据着堆空间,我们的程序想长期稳定运行简直是个梦...

    来吧,我们做个测试,探一探这个“万恶之源”的真面目:

//## class CComplex
class CComplex {
        Friends    
    
public :

        Constructors and destructors    
    
    //## operation CComplex(double,double)
    CComplex(double a = 0.0, double b = 0.0) : r(a), c(b){}
    
    //## operation ~CComplex()
    virtual ~CComplex();
    
        Attributes    

protected :
	union {
	struct {
		double r;		//## attribute r
		double c;		//## attribute c
	};
	CComplex * next;
	};   
};

   

static void signal_handler(int signum)
{
	cout << "Get a signal " << signum << endl;
	DEBUG_BACKTRACE();
	exit(1);
}
/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  main
 *  Description:  
 * =====================================================================================
 */
int main ( int argc, char *argv[] )
{
	CComplex * _array[50000];
	
	signal(SIGSEGV, signal_handler);
	signal(SIGABRT, signal_handler);
	DEBUG_TIME_BEGIN();
	for(int i = 0; i < 5000; i ++)
	{
		for(int j = 0; j < 50000; j ++)
		{
			_array[j]	=	new CComplex(i, j);
		}

		for(int j = 0; j < 50000; j ++)
		{
			delete _array[j];
		}
	}

	DEBUG_TIME_DUR();
	DEBUG_TIME_END();

	return 0;
}				/* ----------  end of function main  ---------- */

    测试结果本稳定在11.6s左右(Ubuntu10.04 64bit)。

    那如果我们提供一份自己的内存管理器后,会有什么不同呢?

#define POOL_SIZE	32
/*
 * =====================================================================================
 *        Class:  IMemoryManager
 *  Description:  
 * =====================================================================================
 */
class IMemoryManager
{
public:
	virtual void * allocate(size_t) = 0;
	virtual void release(void *) = 0;
protected:

private:

}; /* -----  end of class IMemoryManager  ----- */


/*
 * =====================================================================================
 *        Class:  CMemoryManager
 *  Description:  
 * =====================================================================================
 */
class CMemoryManager : public IMemoryManager
{
	struct FreeStore
	{
		FreeStore * next;
	};

	void expandPoolSize()
	{
//		cout << "Expand Pool Size!" << endl;
		size_t size	=	(sizeof(CComplex) > sizeof(FreeStore *)) ? 
			sizeof(CComplex) : sizeof(FreeStore *);

		FreeStore * head	=	reinterpret_cast<FreeStore *>(new char[size]);
		freeStoreHead	=	head;

		for(int i = 0; i < POOL_SIZE; i ++)
		{
			head->next	=	reinterpret_cast<FreeStore *>(new char[size]);
			head	=	head->next;
		}

		head->next	=	NULL;
	}
	void cleanup()
	{
//		cout << "Clean Up!" << endl;
		FreeStore * nextPtr	=	freeStoreHead;

		for(; nextPtr; nextPtr	=	freeStoreHead)
		{
			freeStoreHead	=	freeStoreHead->next;
			delete [] nextPtr;
		}
	}
	FreeStore * freeStoreHead;
public:
	CMemoryManager ()                           /* constructor */
	{
		cout << "Create CMemoryManager Object!" << endl;
		freeStoreHead	=	NULL;
		expandPoolSize();
	}

	virtual ~CMemoryManager()
	{
		cout << "Destory CMemoryManager Object!" << endl;
		cleanup();
	}

	virtual void * allocate(size_t size)
	{
		if(freeStoreHead == NULL)
			expandPoolSize();

		FreeStore * head	=	freeStoreHead;
		freeStoreHead	=	head->next;

		return head;
	}

	virtual void release(void * obj)
	{
		FreeStore * head	=	static_cast<FreeStore *>(obj);
		head->next	=	freeStoreHead;
		freeStoreHead	=	head;
	}
protected:

private:

}; /* -----  end of class CMemoryManager  ----- */
//## class CComplex
class CComplex {
        Friends    
    
public :

        Constructors and destructors    
    
    //## operation CComplex(double,double)
    CComplex(double a = 0.0, double b = 0.0) : r(a), c(b){}
    
    //## operation ~CComplex()
    virtual ~CComplex();

	void *operator new(size_t) throw();
	void operator delete(void *);
    
        Attributes    

protected :
	union {
	struct {
		double r;		//## attribute r
		double c;		//## attribute c
	};
	CComplex * next;
	};   
};
CMemoryManager gMemoryManager;
//## class CComplex
void * CComplex::operator new(size_t size) throw()
{
	return gMemoryManager.allocate(size);
}

void CComplex::operator delete(void * obj)
{
	gMemoryManager.release(obj);
}
    经过测试,在使用了自己内存管理之后,平均的执行时间为7.7s左右,提高了34%。
    这个内存管理器存在一个问题是:不支持多线程互斥,因此,在单线程环境中,可以有效提高内存使用的效率(虽然不如参考资料提到的那么多)。

    接下来,我将对其进行模板化,使其支持额外的数据类型,并测试其增加互斥后的性能,完整代码会放到空间的代码分类中。

    参考资料:http://www.ibm.com/developerworks/cn/education/aix/au-memorymanager/index.html

    续:经过测试,增加mutex互斥后,平均执行时间为8.4s,可见去除掉内核态的切换,多线程安全的new的性能仍有很大程度的提升。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值