3 // Hoard threadtest allocator test
5 #include "alloc/michael_allocator.h"
7 #include <cds/os/timer.h>
8 #include <cds/os/topology.h>
10 #include "cppunit/thread.h"
14 static size_t s_nPassCount = 1000;
15 static size_t s_nBlockCount = 10000;
16 static size_t s_nMinBlockSize = 16;
17 static size_t s_nMaxBlockSize = 1024;
18 static size_t s_nMaxThreadCount = 32;
20 static size_t s_nPassPerThread;
22 static size_t s_nCurBlockSize;
24 # define TEST_ALLOC(X, CLASS) void X() { test< CLASS >( false ) ; }
25 # define TEST_ALLOC_STAT(X, CLASS) void X() { test< CLASS >( true ) ; }
28 In Threadtest, each thread performs s_nPassCount iterations of allocating s_nBlockCount
29 s_nCurBlockSize-byte blocks and then freeing them in order. The benchmarks capture
30 allocator latency and scalability under regular private allocation patterns.
32 class Hoard_ThreadTest: public CppUnitMini::TestCase
34 template <class ALLOC>
35 class Thread: public CppUnitMini::TestThread
38 typedef typename ALLOC::value_type value_type;
41 virtual Thread * clone()
43 return new Thread( *this );
48 Thread( CppUnitMini::ThreadPool& pool, ALLOC& a )
49 : CppUnitMini::TestThread( pool )
53 : CppUnitMini::TestThread( src )
54 , m_Alloc( src.m_Alloc )
57 Hoard_ThreadTest& getTest()
59 return reinterpret_cast<Hoard_ThreadTest&>( m_Pool.m_Test );
64 cds::threading::Manager::attachThread();
65 m_arr = new value_type *[s_nBlockCount];
70 cds::threading::Manager::detachThread();
75 size_t nSize = s_nCurBlockSize / sizeof(value_type);
76 for ( size_t nPass = 0; nPass < s_nPassPerThread; ++nPass ) {
77 value_type ** pCell = m_arr;
78 for ( size_t i = 0; i < s_nBlockCount; ++i, ++pCell ) {
79 *pCell = m_Alloc.allocate( nSize, nullptr );
80 CPPUNIT_ASSERT( *pCell != nullptr );
83 memset( *pCell, 0, nSize );
85 memset( *pCell, 0, 16 );
86 memset( ((char *)(*pCell)) + nSize * sizeof(value_type) - 16, 0, 16 );
89 CPPUNIT_ASSERT( (reinterpret_cast<uintptr_t>(*pCell) & (ALLOC::alignment - 1)) == 0 );
92 for ( size_t i = 0; i < s_nBlockCount; ++i, ++pCell ) {
93 m_Alloc.deallocate( *pCell, 1 );
99 template <class ALLOC>
100 void test( size_t nThreadCount )
103 cds::OS::Timer timer;
105 CPPUNIT_MSG( "Thread count=" << nThreadCount );
106 s_nPassPerThread = s_nPassCount / nThreadCount;
108 CppUnitMini::ThreadPool pool( *this );
109 pool.add( new Thread<ALLOC>( pool, alloc ), nThreadCount );
111 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
114 template <class ALLOC>
115 void test( bool bStat)
117 s_nCurBlockSize = s_nMinBlockSize;
118 while ( s_nCurBlockSize <= s_nMaxBlockSize ) {
119 CPPUNIT_MSG( "Block size=" << s_nCurBlockSize << ", block count=" << s_nBlockCount << ", pass count=" << s_nPassCount << " per thread" );
120 for ( size_t nThreadCount = 1; nThreadCount <= s_nMaxThreadCount; nThreadCount *= 2 ) {
121 summary_stat stBegin;
123 ALLOC::stat(stBegin);
125 test<ALLOC>( nThreadCount );
129 ALLOC::stat( stEnd );
131 std::cout << "\nStatistics:\n"
135 std::cout << "\nDelta statistics:\n"
140 s_nCurBlockSize *= 2;
144 void setUpParams( const CppUnitMini::TestCfg& cfg )
146 s_nPassCount = cfg.getULong( "PassCount", 1000 );
147 s_nBlockCount = cfg.getULong( "BlockCount", 10000 );
148 s_nMinBlockSize = cfg.getULong( "MinBlockSize", 16 );
149 s_nMaxBlockSize = cfg.getULong( "MaxBlockSize", 1024 );
150 s_nMaxThreadCount = cfg.getUInt( "MaxThreadCount", 32 );
151 if ( s_nMaxThreadCount == 0 )
152 s_nMaxThreadCount = cds::OS::topology::processor_count() * 2;
155 typedef MichaelAlignHeap_Stat<int, 64> t_MichaelAlignHeap_Stat;
156 typedef MichaelAlignHeap_NoStat<int,64> t_MichaelAlignHeap_NoStat;
157 typedef system_aligned_allocator<int, 64> t_system_aligned_allocator;
159 TEST_ALLOC_STAT( michael_heap_stat, MichaelHeap_Stat<int> )
160 TEST_ALLOC( michael_heap_nostat, MichaelHeap_NoStat<int> )
161 TEST_ALLOC( std_alloc, std_allocator<int> )
163 TEST_ALLOC_STAT( michael_alignheap_stat, t_MichaelAlignHeap_Stat )
164 TEST_ALLOC( michael_alignheap_nostat, t_MichaelAlignHeap_NoStat )
165 TEST_ALLOC( system_aligned_alloc, t_system_aligned_allocator )
167 CPPUNIT_TEST_SUITE( Hoard_ThreadTest )
168 CPPUNIT_TEST( std_alloc )
169 CPPUNIT_TEST( michael_heap_stat )
170 CPPUNIT_TEST( michael_heap_nostat )
172 CPPUNIT_TEST( system_aligned_alloc )
173 CPPUNIT_TEST( michael_alignheap_stat )
174 CPPUNIT_TEST( michael_alignheap_nostat )
176 CPPUNIT_TEST_SUITE_END();
179 } // namespace memory
180 CPPUNIT_TEST_SUITE_REGISTRATION( memory::Hoard_ThreadTest );