再探小型对象分配技巧
再探小型对象分配技巧(Small-Object Allocation)
/*
?* References, 参考文献:
?* [1]. Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design?
?* Patterns Applied". Copyright (c) 2001. Addison-Wesley.
?*
?* 本文研究的源代码取自loki库SmallObj.h & SmallObj.cpp?
?*/
?
?pool_是个FixedAllocator数组,为了能够简单而且高效地查找到哪个FixedAllocator负责哪个大小的内存块,所以数组下标index处理index大小的内存块。但是事情总是没有那么完美的,不是吗?也许某个应用程序只需产生4字节和32字节的大小的两种对象,再没其他的了。但是pool_还是要分配负责除此两个大小以外的FixedAllocator。
void SmallObjAllocator::Deallocate( void * p, std::size_t numBytes )template < template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL, std::size_t chunkSize = LOKI_DEFAULT_CHUNK_SIZE, std::size_t maxSmallObjectSize = LOKI_MAX_SMALL_OBJECT_SIZE, std::size_t objectAlignSize = LOKI_DEFAULT_OBJECT_ALIGNMENT, template <class> class LifetimePolicy = LOKI_DEFAULT_SMALLOBJ_LIFETIME, class MutexPolicy = LOKI_DEFAULT_MUTEX > class SmallObject : public SmallObjectBase< ThreadingModel, chunkSize, maxSmallObjectSize, objectAlignSize, LifetimePolicy, MutexPolicy > { public: virtual ~SmallObject() {} protected: inline SmallObject( void ) {} private: /// Copy-constructor is not implemented. SmallObject( const SmallObject & ); /// Copy-assignment operator is not implemented. SmallObject & operator = ( const SmallObject & ); }; // end class SmallObjecttemplate < template <class, class> class ThreadingModel, std::size_t chunkSize, std::size_t maxSmallObjectSize, std::size_t objectAlignSize, template <class> class LifetimePolicy, class MutexPolicy > class SmallObjectBase { public: typedef AllocatorSingleton< ThreadingModel, chunkSize, maxSmallObjectSize, objectAlignSize, LifetimePolicy > ObjAllocatorSingleton; private: typedef ThreadingModel< ObjAllocatorSingleton, MutexPolicy > MyThreadingModel; typedef typename ObjAllocatorSingleton::MyAllocatorSingleton MyAllocatorSingleton; public: static void * operator new ( std::size_t size, const std::nothrow_t & ) throw () { typename MyThreadingModel::Lock lock; (void)lock; // get rid of warning return MyAllocatorSingleton::Instance().Allocate( size, false ); } /// Placement single-object new merely calls global placement new. inline static void * operator new ( std::size_t size, void * place ) { return ::operator new( size, place ); } static void operator delete ( void * p, std::size_t size ) throw () { typename MyThreadingModel::Lock lock; (void)lock; // get rid of warning MyAllocatorSingleton::Instance().Deallocate( p, size ); } static void operator delete ( void * p, const std::nothrow_t & ) throw() { typename MyThreadingModel::Lock lock; (void)lock; // get rid of warning MyAllocatorSingleton::Instance().Deallocate( p ); } /// Placement single-object delete merely calls global placement delete. inline static void operator delete ( void * p, void * place ) { ::operator delete ( p, place ); } protected: inline SmallObjectBase( void ) {} inline SmallObjectBase( const SmallObjectBase & ) {} inline SmallObjectBase & operator = ( const SmallObjectBase & ) { return *this; } inline ~SmallObjectBase() {} }; // end class SmallObjectBase?在上述实现过程中,作者Andrei又运用了一个C++编译器的技巧。在重载::operator delete(void *p, size_t size)时,实际上是需要SmallObject提供被析构对象的大小(运用了C++编译器删除对象前,即时产生一些代码计算被删除对象的大小),提供给SmallObject重载delete函数的“大小”参数来源于此。因此SmallObject提供了一个虚析构函数。因此,从SmallObject派生的任何类都会继承这个虚析构函数。
?
另一个问题就是对于整个程序而言,只需要一个唯一的SmallObjAllocator,因此SmallObject在包装第三层时,使用了Singleton模式。(Singleton不在本篇讨论范围内,在此不加描述)。
?
小结:
?????? 正在写测试程序,对比性能;待续。。。