很久没有写blog了,一直很懒惰。这几天写了个内存对象池,用于对需要频繁的分配、释放做优化。
在windows和linux下分别试验,结果linux下只有6倍的提升(原因是linux系统内核对小对象本身就有内存对象池优化)。
测试中还发现原来stlPort的vector居然和标准有所出入,msvc8的stl倒是表现很准确(不过,ms的basic_ifstream似乎有问题)。
/**
* 以下代码由张家旺编写完成于2007-3-29,借用请保留该声明。
*/
#ifdef _MSC_VER
# pragma once
#endif
#ifndef __MEM_POOL__
#define __MEM_POOL__
namespace useful
{
template < class T > class allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T *pointer;
typedef const T *const_pointer;
typedef T &reference;
typedef const T &const_reference;
typedef T value_type;
pointer address( reference x ) const
{
return &x;
}
const_pointer address( const_reference x ) const
{
return &x;
}
void construct( pointer p,const T &t )
{
new ( p ) T( t );
}
void destroy( pointer p )
{
p->~T();
}
pointer allocate( size_type n = 1,void *hint = 0 );
void deallocate( pointer p,size_type n = 1 );
pointer constructEx( const T &t )
{
pointer p = allocate( 1,0 );
new ( p ) T( t );
return p;
}
void destroyEx( pointer p )
{
p->~T();
deallocate( p,1 );
}
};
template < class T1, class T2 >
bool operator==( const allocator< T1 > &a1,const allocator< T2 > &a2 ) throw()
{
return &a1 == &a2;
}
template < class T1, class T2 >
bool operator!=( const allocator< T1 > &a1,const allocator< T2 > &a2 ) throw()
{
return &a1 != &a2;
}
template < class T,int N >
class allocator1 : public allocator< T >
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T *pointer;
typedef const T *const_pointer;
typedef T &reference;
typedef const T &const_reference;
typedef T value_type;
template < class U > struct rebind { typedef allocator1< U,N > other; };
allocator1( void ) throw();
template < class U > allocator1( const allocator1< U,N > & ) throw() {}
~allocator1( void ) throw();
size_type max_size( void ) const throw();
pointer allocate( size_type n = 1,void *hint = 0 );
void deallocate( pointer p,size_type n = 1 );
private:
struct mem_node {
char buf[sizeof(T)*N];
void *use[N];
size_type reuse;
struct mem_node *next;
} m_head;
static void initialize( struct mem_node &node );
static void finalize( struct mem_node &node );
static void *allocate( struct mem_node &node );
static bool deallocate( void *p,struct mem_node &node );
};
template < class T,int N >
void allocator1< T,N >::initialize( struct mem_node &node )
{
for( size_type i = 0; i < N; ++i )
node.use[i] = node.buf+sizeof(T)*i;
node.reuse = N;
node.next = 0;
}
template < class T,int N >
allocator1< T,N >::allocator1( void ) throw()
{
initialize( m_head );
}
template < class T,int N >
void allocator1< T,N >::finalize( struct mem_node &node )
{
if( node.next != 0 ) finalize( *node.next );
delete &node;
}
template < class T,int N >
allocator1< T,N >::~allocator1( void ) throw()
{
if( m_head.next != 0 ) finalize( *m_head.next );
}
template < class T,int N >
typename allocator1< T,N >::size_type
allocator1< T,N >::max_size( void ) const throw()
{
const struct mem_node *node = &m_head;
while( node != 0 && node->reuse < = 0 ) node = node->next;
return node == 0 ? N : node->reuse;
}
template < class T,int N >
void *allocator1< T,N >::allocate( struct mem_node &node )
{
return node.reuse > 0 ? node.use[--node.reuse] : 0;
}
template < class T,int N >
typename allocator1< T,N >::pointer
allocator1< T,N >::allocate( size_type,void *hint )
{
void *p;
struct mem_node *node = &m_head;
while( (p=allocate(*node)) == 0 )
{
if( node->next != 0 ) node = node->next;
else
{
struct mem_node *node_ = new struct mem_node;
initialize( *node_ );
node = node->next = node_;
}
}
return static_cast< pointer >( p );
}
template < class T,int N >
bool allocator1< T,N >::deallocate( void *p,struct mem_node &node )
{
if( p < node.buf || p >= node.use ) return false;
node.use[node.reuse++] = p;
return true;
}
template < class T,int N >
void allocator1< T,N >::deallocate( pointer p,size_type n )
{
struct mem_node *node = &m_head,*prev;
while( !deallocate(p,*node) ) prev = node,node = node->next;
if( node != &m_head && node->reuse >= N )
{
prev->next = node->next;
delete node;
}
}
template < class T >
class allocator2 : public allocator< T >
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T *pointer;
typedef const T *const_pointer;
typedef T &reference;
typedef const T &const_reference;
typedef T value_type;
template < class U > struct rebind { typedef allocator2< U > other; };
allocator2( size_type num = 1024 ) throw();
template < class U > allocator2( const allocator2< U > & ) throw() {}
~allocator2( void ) throw();
size_type max_size( void ) const throw();
pointer allocate( size_type n = 1,void *hint = 0 );
void deallocate( pointer p,size_type n = 1 );
private:
struct mem_node {
void *buf;
void **use;
size_type num,reuse;
struct mem_node *next;
} *m_head;
static mem_node &allocate0( size_type num );
static void deallocate0( mem_node &node );
static void finalize( mem_node &node );
static void *allocate0( mem_node &node );
static bool deallocate0( void *p,mem_node &node );
};
template < class T >
typename allocator2< T >::mem_node &allocator2< T >::allocate0( size_type num )
{
char *p = new char[sizeof(mem_node)+num*(sizeof(T)+sizeof(void *))];
mem_node &node = *reinterpret_cast< mem_node * >( p );
node.buf = ( p += sizeof(mem_node) );
node.use = reinterpret_cast< void ** >( p + sizeof(T)*num );
for( size_type i = 0; i < num; ++i )
node.use[i] = p + sizeof(T)*i;
node.reuse = node.num = num;
node.next = 0;
return node;
}
template < class T >
void allocator2< T >::deallocate0( mem_node &node )
{
char *p = reinterpret_cast< char * >( &node );
delete[] p;
}
template < class T >
allocator2< T >::allocator2( size_type num ) throw() : m_head( &allocate0(num) )
{
}
template < class T >
void allocator2< T >::finalize( mem_node &node )
{
if( node.next != 0 ) finalize( *node.next );
deallocate0( node );
}
template < class T >
allocator2< T >::~allocator2( void ) throw()
{
finalize( *m_head );
}
template < class T >
typename allocator2< T >::size_type
allocator2< T >::max_size( void ) const throw()
{
const mem_node *node = m_head,*prev;
while( node != 0 && node->reuse < = 0 ) prev = node,node = node->next;
return node == 0 ? prev.num : node->reuse;
}
template < class T >
void *allocator2< T >::allocate0( mem_node &node )
{
return node.reuse > 0 ? node.use[--node.reuse] : 0;
}
template < class T >
typename allocator2< T >::pointer
allocator2< T >::allocate( size_type,void *hint )
{
void *p;
mem_node *node = m_head;
while( (p=allocate0(*node)) == 0 )
{
if( node->next != 0 ) node = node->next;
else node = node->next = &allocate0( node->num );
}
return static_cast< pointer >( p );
}
template < class T >
bool allocator2< T >::deallocate0( void *p,mem_node &node )
{
if( p < node.buf || p >= node.use ) return false;
node.use[node.reuse++] = p;
return true;
}
template < class T >
void allocator2< T >::deallocate( pointer p,size_type n )
{
mem_node *node = m_head,*prev;
while( !deallocate0(p,*node) ) prev = node,node = node->next;
if( node != m_head && node->reuse >= node->num )
{
prev->next = node->next;
deallocate0( *node );
}
}
};
#endif //__MEM_POOL__