3 // Random allocator test
5 #include "alloc/michael_allocator.h"
6 #include "alloc/random_gen.h"
8 #include <cds/os/timer.h>
9 #include <cds/os/topology.h>
11 #include "cppunit/thread.h"
15 static size_t s_nMaxThreadCount = 32;
16 static unsigned int s_nMinBlockSize = 8;
17 static unsigned int s_nMaxBlockSize = 1024;
18 //static size_t s_nBlocksPerThread = 1000;
19 static size_t s_nPassCount = 100000;
20 static size_t s_nDataSize = 1000;
22 static size_t s_nPassPerThread;
25 cds::sync::spin m_access;
30 , m_pszBlock( nullptr )
33 Item& operator =(Item const& i)
35 m_pszBlock = i.m_pszBlock;
39 typedef std::vector<Item> item_array;
41 # define TEST_ALLOC(X, CLASS) void X() { test< CLASS >(false); }
42 # define TEST_ALLOC_STAT(X, CLASS) void X() { test< CLASS >(true) ; }
44 class Random_Alloc: public CppUnitMini::TestCase
48 template <class ALLOC>
49 class Thread: public CppUnitMini::TestThread
52 typedef typename ALLOC::value_type value_type;
54 randomGen<size_t> m_rndGen;
56 virtual Thread * clone()
58 return new Thread( *this );
62 Thread( CppUnitMini::ThreadPool& pool, ALLOC& a )
63 : CppUnitMini::TestThread( pool )
67 : CppUnitMini::TestThread( src )
68 , m_Alloc( src.m_Alloc )
71 Random_Alloc& getTest()
73 return reinterpret_cast<Random_Alloc&>( m_Pool.m_Test );
76 virtual void init() { cds::threading::Manager::attachThread() ; }
77 virtual void fini() { cds::threading::Manager::detachThread() ; }
81 item_array& arr = getTest().m_Data;
82 for ( size_t nPass = 0; nPass < s_nPassPerThread; ) {
83 size_t nIdx = m_rndGen( size_t(0), s_nDataSize - 1 );
84 Item & item = arr.at(nIdx);
85 if ( item.m_access.try_lock() ) {
86 if ( item.m_pszBlock ) {
87 m_Alloc.deallocate( item.m_pszBlock, 1 );
88 item.m_pszBlock = nullptr;
92 item.m_pszBlock = m_Alloc.allocate( nSize = m_rndGen( s_nMinBlockSize, s_nMaxBlockSize ), nullptr );
95 memset( item.m_pszBlock, 0, nSize );
97 memset( item.m_pszBlock, 0, 16 );
98 memset( ((char *) item.m_pszBlock) + nSize * sizeof(*item.m_pszBlock) - 16, 0, 16 );
101 item.m_access.unlock();
109 template <class ALLOC>
110 void test( size_t nThreadCount )
114 CPPUNIT_MSG( "Thread count=" << nThreadCount );
115 s_nPassPerThread = s_nPassCount / nThreadCount;
117 CppUnitMini::ThreadPool pool( *this );
118 pool.add( new Thread<ALLOC>( pool, alloc ), nThreadCount );
120 cds::OS::Timer timer;
122 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
124 for ( size_t i = 0; i < m_Data.size(); ++i ) {
125 if ( m_Data[i].m_pszBlock ) {
126 alloc.deallocate( m_Data[i].m_pszBlock, 1 );
127 m_Data[i].m_pszBlock = nullptr;
132 template <class ALLOC>
133 void test( bool bStat )
135 CPPUNIT_MSG( "Block size=" << s_nMinBlockSize << "-" << s_nMaxBlockSize
136 << ", pass count=" << s_nPassCount << ", data size=" << s_nDataSize );
138 m_Data.resize( s_nDataSize );
140 for ( size_t nThreadCount = 2; nThreadCount <= s_nMaxThreadCount; nThreadCount *= 2 ) {
141 summary_stat stBegin;
143 ALLOC::stat( stBegin );
145 test<ALLOC>( nThreadCount );
149 ALLOC::stat( stEnd );
151 std::cout << "\nStatistics:\n"
155 std::cout << "\nDelta statistics:\n"
164 void setUpParams( const CppUnitMini::TestCfg& cfg )
166 s_nDataSize = cfg.getULong( "DataSize", 1000 );
167 s_nPassCount = cfg.getULong( "PassCount", 100000 );
168 s_nMinBlockSize = cfg.getUInt( "MinBlockSize", 8 );
169 s_nMaxBlockSize = cfg.getUInt( "MaxBlockSize", 1024 );
170 s_nMaxThreadCount = cfg.getUInt( "MaxThreadCount", 32 );
171 if ( s_nMaxThreadCount == 0 )
172 s_nMaxThreadCount = cds::OS::topology::processor_count() * 2;
173 if ( s_nMaxThreadCount < 2 )
174 s_nMaxThreadCount = 2;
177 typedef MichaelAlignHeap_Stat<char, 32> t_MichaelAlignHeap_Stat;
178 typedef MichaelAlignHeap_NoStat<char,32> t_MichaelAlignHeap_NoStat;
179 typedef system_aligned_allocator<char, 32> t_system_aligned_allocator;
181 TEST_ALLOC_STAT( michael_heap_stat, MichaelHeap_Stat<char> )
182 TEST_ALLOC( michael_heap_nostat, MichaelHeap_NoStat<char> )
183 TEST_ALLOC( std_alloc, std_allocator<char> )
185 TEST_ALLOC_STAT( michael_alignheap_stat,t_MichaelAlignHeap_Stat )
186 TEST_ALLOC( michael_alignheap_nostat, t_MichaelAlignHeap_NoStat )
187 TEST_ALLOC( system_aligned_alloc, t_system_aligned_allocator )
189 CPPUNIT_TEST_SUITE( Random_Alloc )
190 CPPUNIT_TEST( michael_heap_stat )
191 CPPUNIT_TEST( michael_heap_nostat )
192 CPPUNIT_TEST( std_alloc )
194 CPPUNIT_TEST( system_aligned_alloc )
195 CPPUNIT_TEST( michael_alignheap_stat )
196 CPPUNIT_TEST( michael_alignheap_nostat )
198 CPPUNIT_TEST_SUITE_END();
201 } // namespace memory
202 CPPUNIT_TEST_SUITE_REGISTRATION( memory::Random_Alloc );