replace with new implementation
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@332 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
de09eec49b
commit
ba524baf5a
2 changed files with 214 additions and 591 deletions
|
@ -1,297 +0,0 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// The Loki Library
|
|
||||||
// Copyright (c) 2005 Peter Kümmel
|
|
||||||
// Copyright (c) 2005 Richard Sposato
|
|
||||||
// Permission to use, copy, modify, distribute and sell this software for any
|
|
||||||
// purpose is hereby granted without fee, provided that the above copyright
|
|
||||||
// notice appear in all copies and that both that copyright notice and this
|
|
||||||
// permission notice appear in supporting documentation.
|
|
||||||
// The authors make no representations about the
|
|
||||||
// suitability of this software for any purpose. It is provided "as is"
|
|
||||||
// without express or implied warranty.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// $Header:
|
|
||||||
|
|
||||||
//#define LOKI_CLASS_LEVEL_THREADING
|
|
||||||
//#define LOKI_OBJECT_LEVEL_THREADING
|
|
||||||
|
|
||||||
// Uncomment this to test new [] and delete [].
|
|
||||||
#define LOKI_SMALL_OBJECT_USE_NEW_ARRAY
|
|
||||||
|
|
||||||
#include "../../include/loki/SmallObj.h"
|
|
||||||
#include "timer.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#undef COMPARE_BOOST_POOL
|
|
||||||
//#define COMPARE_BOOST_POOL
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
|
||||||
#include <boost\pool\object_pool.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
|
|
||||||
template<unsigned int N>
|
|
||||||
class ThisIsASmallObject
|
|
||||||
{
|
|
||||||
char data[N];
|
|
||||||
};
|
|
||||||
|
|
||||||
template<unsigned int N, class T>
|
|
||||||
struct Base : public ThisIsASmallObject<N>, public T {};
|
|
||||||
|
|
||||||
template<unsigned int N>
|
|
||||||
struct Base<N, void> : public ThisIsASmallObject<N> {};
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
|
||||||
|
|
||||||
template<unsigned int N>
|
|
||||||
class BoostPoolNew : public Base<N,void>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static boost::object_pool< BoostPoolNew<N> > BoostPool;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// Throwing single-object new throws bad_alloc when allocation fails.
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
/// @note MSVC complains about non-empty exception specification lists.
|
|
||||||
static void * operator new ( std::size_t )
|
|
||||||
#else
|
|
||||||
static void * operator new ( std::size_t ) throw ( std::bad_alloc )
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return BoostPool.malloc();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Non-throwing single-object new returns NULL if allocation fails.
|
|
||||||
static void * operator new ( std::size_t, const std::nothrow_t & ) throw ()
|
|
||||||
{
|
|
||||||
return BoostPool.malloc();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Single-object delete.
|
|
||||||
static void operator delete ( void * p ) throw ()
|
|
||||||
{
|
|
||||||
BoostPool.free( reinterpret_cast< BoostPoolNew * >( p ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Non-throwing single-object delete is only called when nothrow
|
|
||||||
new operator is used, and the constructor throws an exception.
|
|
||||||
*/
|
|
||||||
static void operator delete ( void * p, const std::nothrow_t & ) throw()
|
|
||||||
{
|
|
||||||
BoostPool.free( reinterpret_cast< BoostPoolNew * >( p ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Placement single-object delete merely calls global placement delete.
|
|
||||||
inline static void operator delete ( void * p, void * place )
|
|
||||||
{
|
|
||||||
::operator delete ( p, place );
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template<unsigned int N>
|
|
||||||
boost::object_pool< BoostPoolNew<N> > BoostPoolNew<N>::BoostPool;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
int array_test_nr = 0;
|
|
||||||
double t100_new = 0;
|
|
||||||
double t100_delete = 0;
|
|
||||||
|
|
||||||
#define LOKI_SMALLOBJ_BENCH(FUNC, CODE_LOOP) \
|
|
||||||
template<class T, int TN> \
|
|
||||||
int FUNC(void**, const int N, int loop, Timer& t, const char* s) \
|
|
||||||
{ \
|
|
||||||
t.start(); \
|
|
||||||
/****************************************************************/ \
|
|
||||||
for (int i=0; i<loop; ++i) \
|
|
||||||
{ \
|
|
||||||
CODE_LOOP \
|
|
||||||
} \
|
|
||||||
/****************************************************************/ \
|
|
||||||
t.stop(); \
|
|
||||||
if(array_test_nr==0) \
|
|
||||||
t.t100 = t.t(); \
|
|
||||||
array_test_nr++; \
|
|
||||||
t.print(t.t(),s); \
|
|
||||||
return t.t(); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define LOKI_SMALLOBJ_BENCH_ARRAY(FUNC, CODE_DECL, CODE_NEW, CODE_DELETE) \
|
|
||||||
template<class T, int TN> \
|
|
||||||
int FUNC(void** arrv, const int N, int loop, Timer& t, const char* s) \
|
|
||||||
{ \
|
|
||||||
\
|
|
||||||
CODE_DECL; \
|
|
||||||
T** arr = reinterpret_cast<T**>(arrv); \
|
|
||||||
t.start(); \
|
|
||||||
/****************************************************************/ \
|
|
||||||
for (int i=0; i<loop; ++i) \
|
|
||||||
{ \
|
|
||||||
CODE_NEW \
|
|
||||||
} \
|
|
||||||
/****************************************************************/ \
|
|
||||||
t.stop(); \
|
|
||||||
std::cout << "1. "; \
|
|
||||||
if(array_test_nr==0) \
|
|
||||||
{ \
|
|
||||||
t.t100 = t.t(); \
|
|
||||||
t100_new = t.t100; \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
t.t100 = t100_new; \
|
|
||||||
t.print(t.t(),s); \
|
|
||||||
\
|
|
||||||
t.start(); \
|
|
||||||
/****************************************************************/ \
|
|
||||||
for (int i=0; i<loop; ++i) \
|
|
||||||
{ \
|
|
||||||
CODE_DELETE \
|
|
||||||
} \
|
|
||||||
/****************************************************************/ \
|
|
||||||
t.stop(); \
|
|
||||||
std::cout << "2. "; \
|
|
||||||
if(array_test_nr==0) \
|
|
||||||
{ \
|
|
||||||
t.t100 = t.t(); \
|
|
||||||
t100_delete = t.t100; \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
t.t100 = t100_delete; \
|
|
||||||
t.print(t.t(),s); \
|
|
||||||
array_test_nr++; \
|
|
||||||
std::cout << "\n"; \
|
|
||||||
return t.t(); \
|
|
||||||
}
|
|
||||||
|
|
||||||
LOKI_SMALLOBJ_BENCH(delete_new ,delete new T;)
|
|
||||||
LOKI_SMALLOBJ_BENCH(delete_new_mal ,std::free(std::malloc(sizeof(T))););
|
|
||||||
LOKI_SMALLOBJ_BENCH(delete_new_all ,std::allocator<T> st;st.deallocate(st.allocate(1), 1);)
|
|
||||||
|
|
||||||
|
|
||||||
LOKI_SMALLOBJ_BENCH(delete_new_array ,delete[] new T[N];)
|
|
||||||
LOKI_SMALLOBJ_BENCH(delete_new_array_mal,std::free(std::malloc(sizeof(T[TN]))););
|
|
||||||
LOKI_SMALLOBJ_BENCH(delete_new_array_all,std::allocator<T[TN]> st;st.deallocate(st.allocate(1), 1);)
|
|
||||||
|
|
||||||
|
|
||||||
LOKI_SMALLOBJ_BENCH_ARRAY(new_del_on_arr , , arr[i] = new T; ,
|
|
||||||
delete arr[i];)
|
|
||||||
LOKI_SMALLOBJ_BENCH_ARRAY(new_del_on_arr_mal, , arr[i] = static_cast<T*>(std::malloc(sizeof(T))); ,
|
|
||||||
std::free(arr[i]);)
|
|
||||||
LOKI_SMALLOBJ_BENCH_ARRAY(new_del_on_arr_all, std::allocator<T> st ,
|
|
||||||
arr[i]=st.allocate(1); ,
|
|
||||||
st.deallocate(arr[i], 1);)
|
|
||||||
|
|
||||||
LOKI_SMALLOBJ_BENCH_ARRAY(new_del_a_on_a , , arr[i] = new T[TN]; ,
|
|
||||||
delete[] arr[i];)
|
|
||||||
LOKI_SMALLOBJ_BENCH_ARRAY(new_del_a_on_a_mal, , arr[i] = static_cast<T*>(std::malloc(sizeof(T[TN]))); ,
|
|
||||||
std::free(arr[i]);)
|
|
||||||
LOKI_SMALLOBJ_BENCH_ARRAY(new_del_a_on_a_all,std::allocator<T[TN]> st ,
|
|
||||||
arr[i]=reinterpret_cast<T*>(st.allocate(1)); ,
|
|
||||||
st.deallocate(reinterpret_cast<T(*)[TN]>(arr[i]), 1);)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef COMPARE_BOOST_POOL
|
|
||||||
#define LOKI_SMALLOBJBECH_ABCD(FUNC,N,LOOP,TIMER,MESSAGE) \
|
|
||||||
array_test_nr = 0; \
|
|
||||||
std::cout << MESSAGE <<"\n"; \
|
|
||||||
FUNC<A,N>(a,N,LOOP,TIMER,"A:"); \
|
|
||||||
FUNC<B,N>(a,N,LOOP,TIMER,"B:"); \
|
|
||||||
FUNC<C,N>(a,N,LOOP,TIMER,"C:"); \
|
|
||||||
FUNC##_all<A,N>(a,N,LOOP,TIMER,"E:"); \
|
|
||||||
FUNC##_mal<A,N>(a,N,LOOP,TIMER,"M:"); \
|
|
||||||
cout << endl << endl;
|
|
||||||
#else
|
|
||||||
#define LOKI_SMALLOBJBECH_ABCD(FUNC,N,LOOP,TIMER,MESSAGE) \
|
|
||||||
array_test_nr = 0; \
|
|
||||||
std::cout << MESSAGE <<"\n"; \
|
|
||||||
FUNC<A,N>(a,N,LOOP,TIMER,"A:"); \
|
|
||||||
FUNC<B,N>(a,N,LOOP,TIMER,"B:"); \
|
|
||||||
FUNC<C,N>(a,N,LOOP,TIMER,"C:"); \
|
|
||||||
FUNC<D,N>(a,N,LOOP,TIMER,"D:"); \
|
|
||||||
FUNC##_all<A,N>(a,N,LOOP,TIMER,"E:"); \
|
|
||||||
FUNC##_mal<A,N>(a,N,LOOP,TIMER,"M:"); \
|
|
||||||
cout << endl << endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<unsigned int Size, int loop>
|
|
||||||
void testSize()
|
|
||||||
{
|
|
||||||
typedef Base<Size, void> A;
|
|
||||||
typedef Base<Size, Loki::SmallObject< Loki::SingleThreaded > > B;
|
|
||||||
typedef Base<Size, Loki::SmallValueObject< Loki::SingleThreaded > > C;
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
|
||||||
typedef BoostPoolNew<Size> D;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cout << "Allocator Benchmark Tests \n" << endl;
|
|
||||||
cout << "A = global new and delete \tsizeof(A) =" << sizeof(A) << endl;
|
|
||||||
cout << "B = Loki::SmallObject \tsizeof(B) =" << sizeof(B) << endl;
|
|
||||||
cout << "C = Loki::SmallValueObject\tsizeof(C) =" << sizeof(C) << endl;
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
|
||||||
cout << "D = boost::object_pool \tsizeof(D) =" << sizeof(D) << endl;
|
|
||||||
#endif
|
|
||||||
cout << "E = std::allocator \tsizeof(D) =" << sizeof(A) << endl;
|
|
||||||
cout << "M = std::malloc/free \tsizeof(D) =" << sizeof(A) << endl;
|
|
||||||
cout << endl << endl;
|
|
||||||
|
|
||||||
Timer t;
|
|
||||||
|
|
||||||
const int N = 20;
|
|
||||||
int N_on_array = 1000*1000;
|
|
||||||
|
|
||||||
void** a= new void*[N_on_array];
|
|
||||||
|
|
||||||
LOKI_SMALLOBJBECH_ABCD(delete_new ,0,loop,t,"'delete new T'");
|
|
||||||
|
|
||||||
LOKI_SMALLOBJBECH_ABCD(delete_new_array ,N,loop,t,"'delete[] new T[N]'");
|
|
||||||
|
|
||||||
LOKI_SMALLOBJBECH_ABCD(new_del_on_arr ,0,N_on_array,t,"1. 'arr[i] = new T' 2. 'delete arr[i]'");
|
|
||||||
|
|
||||||
LOKI_SMALLOBJBECH_ABCD(new_del_a_on_a ,N,N_on_array,t,"1. 'arr[i] = new T[N]' 2. 'delete[] arr[i]'");
|
|
||||||
|
|
||||||
|
|
||||||
delete [] a;
|
|
||||||
|
|
||||||
cout << endl << endl;
|
|
||||||
Loki::AllocatorSingleton<>::ClearExtraMemory();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
cout << endl;
|
|
||||||
|
|
||||||
const int loop = 1000*1000;
|
|
||||||
|
|
||||||
testSize<4,loop>();
|
|
||||||
testSize<8,loop>();
|
|
||||||
testSize<16,loop>();
|
|
||||||
testSize<32,loop>();
|
|
||||||
testSize<64,loop>();
|
|
||||||
|
|
||||||
|
|
||||||
system("PAUSE");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// $Log:
|
|
||||||
|
|
|
@ -25,26 +25,27 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
//#define COMPARE_BOOST_POOL
|
//#define COMPARE_BOOST_POOL
|
||||||
#ifdef COMPARE_BOOST_POOL
|
#ifdef COMPARE_BOOST_POOL
|
||||||
#include <boost\pool\object_pool.hpp>
|
#include <boost\pool\object_pool.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
template<unsigned int N>
|
template<unsigned int N>
|
||||||
class ThisIsASmallObject
|
class ThisIsASmallObject
|
||||||
{
|
{
|
||||||
char data[N];
|
char data[N];
|
||||||
};
|
};
|
||||||
|
|
||||||
template<unsigned int N, class T>
|
template<unsigned int N, class T>
|
||||||
struct Base : public ThisIsASmallObject<N>, public T {};
|
struct Base : public ThisIsASmallObject<N>, public T
|
||||||
|
{};
|
||||||
|
|
||||||
template<unsigned int N>
|
template<unsigned int N>
|
||||||
struct Base<N, void> : public ThisIsASmallObject<N> {};
|
struct Base<N, void> : public ThisIsASmallObject<N>
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
#ifdef COMPARE_BOOST_POOL
|
||||||
|
@ -53,51 +54,51 @@ template<unsigned int N>
|
||||||
class BoostPoolNew : public Base<N,void>
|
class BoostPoolNew : public Base<N,void>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static boost::object_pool< BoostPoolNew<N> > BoostPool;
|
static boost::object_pool< BoostPoolNew<N> > BoostPool;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Throwing single-object new throws bad_alloc when allocation fails.
|
/// Throwing single-object new throws bad_alloc when allocation fails.
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
/// @note MSVC complains about non-empty exception specification lists.
|
/// @note MSVC complains about non-empty exception specification lists.
|
||||||
static void * operator new ( std::size_t )
|
static void * operator new ( std::size_t )
|
||||||
#else
|
#else
|
||||||
static void * operator new ( std::size_t ) throw ( std::bad_alloc )
|
static void * operator new ( std::size_t ) throw ( std::bad_alloc )
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
return BoostPool.malloc();
|
return BoostPool.malloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Non-throwing single-object new returns NULL if allocation fails.
|
/// Non-throwing single-object new returns NULL if allocation fails.
|
||||||
static void * operator new ( std::size_t, const std::nothrow_t & ) throw ()
|
static void * operator new ( std::size_t, const std::nothrow_t & ) throw ()
|
||||||
{
|
{
|
||||||
return BoostPool.malloc();
|
return BoostPool.malloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Placement single-object new merely calls global placement new.
|
/// Placement single-object new merely calls global placement new.
|
||||||
inline static void * operator new ( std::size_t size, void * place )
|
inline static void * operator new ( std::size_t size, void * place )
|
||||||
{
|
{
|
||||||
return ::operator new( size, place );
|
return ::operator new( size, place );
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Single-object delete.
|
/// Single-object delete.
|
||||||
static void operator delete ( void * p ) throw ()
|
static void operator delete ( void * p ) throw ()
|
||||||
{
|
{
|
||||||
BoostPool.free( reinterpret_cast< BoostPoolNew * >( p ) );
|
BoostPool.free( reinterpret_cast< BoostPoolNew * >( p ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Non-throwing single-object delete is only called when nothrow
|
/** Non-throwing single-object delete is only called when nothrow
|
||||||
new operator is used, and the constructor throws an exception.
|
new operator is used, and the constructor throws an exception.
|
||||||
*/
|
*/
|
||||||
static void operator delete ( void * p, const std::nothrow_t & ) throw()
|
static void operator delete ( void * p, const std::nothrow_t & ) throw()
|
||||||
{
|
{
|
||||||
BoostPool.free( reinterpret_cast< BoostPoolNew * >( p ) );
|
BoostPool.free( reinterpret_cast< BoostPoolNew * >( p ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Placement single-object delete merely calls global placement delete.
|
/// Placement single-object delete merely calls global placement delete.
|
||||||
inline static void operator delete ( void * p, void * place )
|
inline static void operator delete ( void * p, void * place )
|
||||||
{
|
{
|
||||||
::operator delete ( p, place );
|
::operator delete ( p, place );
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -107,293 +108,212 @@ boost::object_pool< BoostPoolNew<N> > BoostPoolNew<N>::BoostPool;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int array_test_nr = 0;
|
||||||
|
double t100_new = 0;
|
||||||
|
double t100_delete = 0;
|
||||||
|
|
||||||
template<class T>
|
#define LOKI_SMALLOBJ_BENCH(FUNC, CODE_LOOP) \
|
||||||
int run_oneline_new_delete(int loop, Timer& t, const char* s)
|
template<class T, int TN> \
|
||||||
{
|
int FUNC(void**, const int N, int loop, Timer& t, const char* s) \
|
||||||
t.start();
|
{ \
|
||||||
/****************************************************************/
|
t.start(); \
|
||||||
for (int i=0; i<loop; ++i)
|
/****************************************************************/ \
|
||||||
{
|
for (int i=0; i<loop; ++i) \
|
||||||
delete new T;
|
{ \
|
||||||
}
|
CODE_LOOP \
|
||||||
/****************************************************************/
|
} \
|
||||||
t.stop();
|
/****************************************************************/ \
|
||||||
t.print(t.t(),s);
|
t.stop(); \
|
||||||
return t.t();
|
if(array_test_nr==0) \
|
||||||
|
t.t100 = t.t(); \
|
||||||
|
array_test_nr++; \
|
||||||
|
t.print(t.t(),s); \
|
||||||
|
return t.t(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
#define LOKI_SMALLOBJ_BENCH_ARRAY(FUNC, CODE_DECL, CODE_NEW, CODE_DELETE) \
|
||||||
int run_new_delete(int loop, Timer& t, const char* s)
|
template<class T, int TN> \
|
||||||
{
|
int FUNC(void** arrv, const int N, int loop, Timer& t, const char* s) \
|
||||||
t.start();
|
{ \
|
||||||
/****************************************************************/
|
\
|
||||||
for (int i=0; i<loop; ++i)
|
CODE_DECL; \
|
||||||
{
|
T** arr = reinterpret_cast<T**>(arrv); \
|
||||||
T* p = new T;
|
t.start(); \
|
||||||
delete p;
|
/****************************************************************/ \
|
||||||
}
|
for (int i=0; i<loop; ++i) \
|
||||||
/****************************************************************/
|
{ \
|
||||||
t.stop();
|
CODE_NEW \
|
||||||
t.print(t.t(),s);
|
} \
|
||||||
return t.t();
|
/****************************************************************/ \
|
||||||
}
|
t.stop(); \
|
||||||
|
cout << "1. "; \
|
||||||
template<class T>
|
if(array_test_nr==0) \
|
||||||
int run_new_delete(T** array, int N, int loop, Timer& t, const char* s)
|
{ \
|
||||||
{
|
t.t100 = t.t(); \
|
||||||
t.start();
|
t100_new = t.t100; \
|
||||||
/****************************************************************/
|
} \
|
||||||
for (int i=0; i<loop; ++i)
|
else \
|
||||||
for (int n=0; n<N; n++)
|
t.t100 = t100_new; \
|
||||||
{
|
t.print(t.t(),s); \
|
||||||
array[n] = new T;
|
\
|
||||||
delete array[n];
|
if(array_test_nr==3) \
|
||||||
}
|
{ \
|
||||||
/****************************************************************/
|
cout << \
|
||||||
t.stop();
|
"2. boost :\tboost::object_pool is not tested because it's too slow"\
|
||||||
t.print(t.t(),s);
|
<< endl << endl; \
|
||||||
return t.t();
|
array_test_nr++; \
|
||||||
}
|
return t.t(); \
|
||||||
|
} \
|
||||||
template<class T>
|
t.start(); \
|
||||||
int run_new(T** array, int loop, Timer& t, const char* s)
|
/****************************************************************/ \
|
||||||
{
|
for (int i=0; i<loop; ++i) \
|
||||||
t.start();
|
{ \
|
||||||
/****************************************************************/
|
CODE_DELETE \
|
||||||
for (int i=0; i<loop; ++i)
|
} \
|
||||||
array[i] = new T;
|
/****************************************************************/ \
|
||||||
/****************************************************************/
|
t.stop(); \
|
||||||
t.stop();
|
cout << "2. "; \
|
||||||
t.print(t.t(),s);
|
if(array_test_nr==0) \
|
||||||
return t.t();
|
{ \
|
||||||
}
|
t.t100 = t.t(); \
|
||||||
template<class T>
|
t100_delete = t.t100; \
|
||||||
int run_delete(T** array, int loop, Timer& t, const char* s)
|
} \
|
||||||
{
|
else \
|
||||||
t.start();
|
t.t100 = t100_delete; \
|
||||||
/****************************************************************/
|
t.print(t.t(),s); \
|
||||||
for (int i=0; i<loop; ++i)
|
array_test_nr++; \
|
||||||
delete array[i];
|
cout << endl; \
|
||||||
/****************************************************************/
|
return t.t(); \
|
||||||
t.stop();
|
|
||||||
t.print(t.t(),s);
|
|
||||||
return t.t();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
LOKI_SMALLOBJ_BENCH(delete_new ,delete new T;)
|
||||||
int run_new_delete_array(int N, int loop, Timer& t, const char* s)
|
LOKI_SMALLOBJ_BENCH(delete_new_mal ,std::free(std::malloc(sizeof(T))););
|
||||||
{
|
LOKI_SMALLOBJ_BENCH(delete_new_all ,std::allocator<T> st;st.deallocate(st.allocate(1), 1);)
|
||||||
t.start();
|
|
||||||
/****************************************************************/
|
|
||||||
for (int i=0; i<loop; ++i)
|
|
||||||
{
|
|
||||||
T* p = new T[N];
|
|
||||||
delete [] p;
|
|
||||||
}
|
|
||||||
/****************************************************************/
|
|
||||||
t.stop();
|
|
||||||
t.print(t.t(),s);
|
|
||||||
return t.t();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
LOKI_SMALLOBJ_BENCH(delete_new_array ,delete[] new T[N];)
|
||||||
int run_new_array( int N, T** array, int loop, Timer& t, const char* s)
|
LOKI_SMALLOBJ_BENCH(delete_new_array_mal,std::free(std::malloc(sizeof(T[TN]))););
|
||||||
{
|
LOKI_SMALLOBJ_BENCH(delete_new_array_all,std::allocator<T[TN]> st;st.deallocate(st.allocate(1), 1);)
|
||||||
t.start();
|
|
||||||
/****************************************************************/
|
LOKI_SMALLOBJ_BENCH_ARRAY(new_del_on_arr , , arr[i] = new T; ,
|
||||||
for (int i=0; i<loop; ++i)
|
delete arr[i];)
|
||||||
array[i] = new T[N];
|
LOKI_SMALLOBJ_BENCH_ARRAY(new_del_on_arr_mal, , arr[i] = static_cast<T*>(std::malloc(sizeof(T))); ,
|
||||||
/****************************************************************/
|
std::free(arr[i]);)
|
||||||
t.stop();
|
LOKI_SMALLOBJ_BENCH_ARRAY(new_del_on_arr_all, std::allocator<T> st ,
|
||||||
t.print(t.t(),s);
|
arr[i]=st.allocate(1); ,
|
||||||
return t.t();
|
st.deallocate(arr[i], 1);)
|
||||||
}
|
|
||||||
template<class T>
|
LOKI_SMALLOBJ_BENCH_ARRAY(new_del_a_on_a , , arr[i] = new T[TN]; ,
|
||||||
int run_delete_array( T** array, int loop, Timer& t, const char* s)
|
delete[] arr[i];)
|
||||||
{
|
LOKI_SMALLOBJ_BENCH_ARRAY(new_del_a_on_a_mal, , arr[i] = static_cast<T*>(std::malloc(sizeof(T[TN]))); ,
|
||||||
t.start();
|
std::free(arr[i]);)
|
||||||
/****************************************************************/
|
LOKI_SMALLOBJ_BENCH_ARRAY(new_del_a_on_a_all,std::allocator<T[TN]> st ,
|
||||||
for (int i=0; i<loop; ++i)
|
arr[i]=reinterpret_cast<T*>(st.allocate(1)); ,
|
||||||
delete [] array[i];
|
st.deallocate(reinterpret_cast<T(*)[TN]>(arr[i]), 1);)
|
||||||
/****************************************************************/
|
|
||||||
t.stop();
|
|
||||||
t.print(t.t(),s);
|
|
||||||
return t.t();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef COMPARE_BOOST_POOL
|
||||||
|
#define LOKI_SMALLOBJBECH_ABCD(FUNC,N,LOOP,TIMER,MESSAGE) \
|
||||||
|
array_test_nr = 0; \
|
||||||
|
cout << MESSAGE << endl; \
|
||||||
|
FUNC<A,N>(a,N,LOOP,TIMER,"new :"); \
|
||||||
|
FUNC<B,N>(a,N,LOOP,TIMER,"SmallObj :"); \
|
||||||
|
FUNC<C,N>(a,N,LOOP,TIMER,"ValueObj :"); \
|
||||||
|
FUNC##_all<A,N>(a,N,LOOP,TIMER,"allocator:"); \
|
||||||
|
FUNC##_mal<A,N>(a,N,LOOP,TIMER,"malloc :"); \
|
||||||
|
cout << endl << endl;
|
||||||
|
#else
|
||||||
|
#define LOKI_SMALLOBJBECH_ABCD(FUNC,N,LOOP,TIMER,MESSAGE) \
|
||||||
|
array_test_nr = 0; \
|
||||||
|
cout << MESSAGE << endl; \
|
||||||
|
FUNC<A,N>(a,N,LOOP,TIMER,"new :"); \
|
||||||
|
FUNC<B,N>(a,N,LOOP,TIMER,"SmallObj :"); \
|
||||||
|
FUNC<C,N>(a,N,LOOP,TIMER,"ValueObj :"); \
|
||||||
|
FUNC<D,N>(a,N,LOOP,TIMER,"boost :"); \
|
||||||
|
FUNC##_all<A,N>(a,N,LOOP,TIMER,"allocator:"); \
|
||||||
|
FUNC##_mal<A,N>(a,N,LOOP,TIMER,"malloc :"); \
|
||||||
|
cout << endl << endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
template<unsigned int Size, int loop>
|
template<unsigned int Size, int loop>
|
||||||
void testSize()
|
void testSize()
|
||||||
{
|
{
|
||||||
typedef Base<Size, void>
|
typedef Base<Size, void> A;
|
||||||
A;
|
typedef Base<Size, Loki::SmallObject< Loki::SingleThreaded > > B;
|
||||||
typedef Base<Size, Loki::SmallObject< Loki::SingleThreaded > >
|
typedef Base<Size, Loki::SmallValueObject< Loki::SingleThreaded > > C;
|
||||||
B;
|
|
||||||
typedef Base<Size, Loki::SmallValueObject< Loki::SingleThreaded > >
|
|
||||||
C;
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
#ifdef COMPARE_BOOST_POOL
|
||||||
typedef BoostPoolNew<Size>
|
typedef BoostPoolNew<Size> D;
|
||||||
D;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cout << "Small-Object Benchmark Tests \n" << endl;
|
cout << endl << endl;
|
||||||
cout << "A = global new and delete \tsizeof(A) =" << sizeof(A) << endl;
|
cout << "Allocator Benchmark Tests with " << Size << " bytes big objects " << endl;
|
||||||
cout << "B = Loki::SmallObject \tsizeof(B) =" << sizeof(B) << endl;
|
cout << endl;
|
||||||
cout << "C = Loki::SmallValueObject\tsizeof(C) =" << sizeof(C) << endl;
|
cout << "new = global new/delete \tsizeof(A) = " << sizeof(A) << endl;
|
||||||
|
cout << "SmallObj = Loki::SmallObject \tsizeof(B) = " << sizeof(B) << endl;
|
||||||
|
cout << "ValueObj = Loki::SmallValueObject\tsizeof(C) = " << sizeof(C) << endl;
|
||||||
#ifdef COMPARE_BOOST_POOL
|
#ifdef COMPARE_BOOST_POOL
|
||||||
cout << "D = boost::object_pool \tsizeof(D) =" << sizeof(D) << endl;
|
cout << "boost = boost::object_pool \tsizeof(D) = " << sizeof(D) << endl;
|
||||||
#endif
|
#endif
|
||||||
cout << endl << endl;
|
cout << "allocator= std::allocator \tsizeof(A) = " << sizeof(A) << endl;
|
||||||
|
cout << "malloc = std::malloc/free \tsizeof(A) = " << sizeof(A) << endl;
|
||||||
|
cout << endl << endl;
|
||||||
|
|
||||||
Timer t;
|
Timer t;
|
||||||
|
|
||||||
t.t100 = 0;
|
const int N = 3;
|
||||||
t.t100 = run_oneline_new_delete<A>(loop,t,"'delete new A' : ");
|
int Narr = 1000*1000;
|
||||||
run_new_delete<B>(loop,t,"'delete new B' : ");
|
|
||||||
run_new_delete<C>(loop,t,"'delete new C' : ");
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
|
||||||
run_new_delete<D>(loop,t,"'delete new D' : ");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cout << endl << endl;
|
void** a= new void*[Narr];
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
t.t100 = 0;
|
cout << loop << " times ";
|
||||||
t.t100 = run_new_delete<A>(loop,t,"new & delete A : ");
|
LOKI_SMALLOBJBECH_ABCD(delete_new ,0,loop,t,"'delete new T'");
|
||||||
run_new_delete<B>(loop,t,"new & delete B : ");
|
|
||||||
run_new_delete<C>(loop,t,"new & delete C : ");
|
cout << "N=" << N <<" : " << loop << " times ";
|
||||||
#ifdef COMPARE_BOOST_POOL
|
LOKI_SMALLOBJBECH_ABCD(delete_new_array ,N,loop,t,"'delete[] new T[N]'");
|
||||||
run_new_delete<D>(loop,t,"new & delete D : ");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cout << endl << endl;
|
cout << "i=0..." << Narr << " : ";
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
LOKI_SMALLOBJBECH_ABCD(new_del_on_arr ,0,Narr,t,"1. 'arr[i] = new T' 2. 'delete arr[i]'");
|
||||||
|
|
||||||
int N = 10000;
|
cout << "i=0..." << Narr << ", N=" << N <<" : ";
|
||||||
int loop2 = loop/N*10;
|
LOKI_SMALLOBJBECH_ABCD(new_del_a_on_a ,N,Narr,t,"1. 'arr[i] = new T[N]' 2. 'delete[] arr[i]'");
|
||||||
|
|
||||||
A** a = new A*[N];
|
|
||||||
B** b = new B*[N];
|
|
||||||
C** c = new C*[N];
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
|
||||||
D** d = new D*[N];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for(int i=0; i<N; i++)
|
|
||||||
{
|
|
||||||
a[i]=0;
|
|
||||||
b[i]=0;
|
|
||||||
c[i]=0;
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
|
||||||
d[i]=0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
t.t100 = 0;
|
|
||||||
t.t100 = run_new_delete(a,N,loop2,t,"new & del. A on array: ");
|
|
||||||
run_new_delete(b,N,loop2,t,"new & del. B on array: ");
|
|
||||||
run_new_delete(c,N,loop2,t,"new & del. C on array: ");
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
|
||||||
run_new_delete(d,N,loop2,t,"new & del. D on array: ");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cout << endl << endl;
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
t.t100 = 0;
|
delete [] a;
|
||||||
t.t100 = run_new(a,N,t,"new A on array : ");
|
|
||||||
run_new(b,N,t,"new B on array : ");
|
cout << "_________________________________________________________________" << endl;
|
||||||
run_new(c,N,t,"new C on array : ");
|
Loki::AllocatorSingleton<>::ClearExtraMemory();
|
||||||
#ifdef COMPARE_BOOST_POOL
|
|
||||||
run_new(d,N,t,"new D on array : ");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cout << endl;
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
t.t100 = 0;
|
|
||||||
t.t100 = run_delete(a,N,t,"delete A on array : ");
|
|
||||||
run_delete(b,N,t,"delete B on array : ");
|
|
||||||
run_delete(c,N,t,"delete C on array : ");
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
|
||||||
run_delete(d,N,t,"delete D on array : ");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cout << endl << endl;
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
N = 5;
|
|
||||||
|
|
||||||
t.t100 = 0;
|
|
||||||
t.t100 = run_new_delete_array<A>(N,loop,t,"new & delete [] A : ");
|
|
||||||
run_new_delete_array<B>(N,loop,t,"new & delete [] B : ");
|
|
||||||
run_new_delete_array<C>(N,loop,t,"new & delete [] C : ");
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
|
||||||
run_new_delete_array<D>(N,loop,t,"new & delete [] D : ");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cout << endl << endl;
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
int count = 100;
|
|
||||||
t.t100 = 0;
|
|
||||||
t.t100 = run_new_array(N,a,count,t,"new [] A on array : ");
|
|
||||||
run_new_array(N,b,count,t,"new [] B on array : ");
|
|
||||||
run_new_array(N,c,count,t,"new [] C on array : ");
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
|
||||||
run_new_array(N,d,count,t,"new [] D on array : ");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cout << endl;
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
t.t100 = 0;
|
|
||||||
t.t100 = run_delete_array(a,count,t,"delete [] A on array : ");
|
|
||||||
run_delete_array(b,count,t,"delete [] B on array : ");
|
|
||||||
run_delete_array(c,count,t,"delete [] C on array : ");
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
|
||||||
run_delete_array(d,count,t,"delete [] D on array : ");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
delete [] a;
|
|
||||||
delete [] b;
|
|
||||||
delete [] c;
|
|
||||||
#ifdef COMPARE_BOOST_POOL
|
|
||||||
delete [] d;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cout << endl << endl;
|
|
||||||
Loki::AllocatorSingleton<>::ClearExtraMemory();
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
cout << endl;
|
const int loop = 1000*1000;
|
||||||
|
|
||||||
const int loop = 700000;
|
cout << endl;
|
||||||
|
|
||||||
testSize<8,loop>();
|
testSize< 2,loop>();
|
||||||
testSize<64,loop>();
|
testSize< 3,loop>();
|
||||||
//testSize<256,loop>();
|
testSize< 8,loop>();
|
||||||
//testSize<1024,loop>();
|
testSize< 9,loop>();
|
||||||
|
testSize<16,loop>();
|
||||||
|
testSize<17,loop>();
|
||||||
|
|
||||||
system("PAUSE");
|
|
||||||
|
|
||||||
return 0;
|
#if defined(__BORLANDC__) || defined(__GNUC__) || defined(_MSC_VER)
|
||||||
|
// Stop console window from closing if run from IDE.
|
||||||
|
system("pause");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// $Log$
|
// $Log$
|
||||||
|
// Revision 1.12 2005/10/29 12:38:22 syntheticpp
|
||||||
|
// replace with new implementation
|
||||||
|
//
|
||||||
// Revision 1.11 2005/10/29 10:21:46 syntheticpp
|
// Revision 1.11 2005/10/29 10:21:46 syntheticpp
|
||||||
// find loki include files without a correct sreach pathand some small fixes
|
// find loki include files without a correct sreach pathand some small fixes
|
||||||
//
|
//
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue