3 // Linux scalability 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 = 10000000;
15 static size_t s_nMaxBlockSize = 64 * 1024 - 16;
16 static size_t s_nMaxThreadCount = 64;
18 static size_t s_nPassPerThread;
20 # define TEST_ALLOC(X, CLASS) void X() { test< CLASS >(false) ; }
21 # define TEST_ALLOC_STAT(X, CLASS) void X() { test< CLASS >(true) ; }
23 class Linux_Scale: public CppUnitMini::TestCase
25 template <class ALLOC>
26 class Thread: public CppUnitMini::TestThread
31 virtual Thread * clone()
33 return new Thread( *this );
38 Thread( CppUnitMini::ThreadPool& pool, ALLOC& a, size_t nSize )
39 : CppUnitMini::TestThread( pool )
44 : CppUnitMini::TestThread( src )
45 , m_Alloc( src.m_Alloc )
46 , m_nSize( src.m_nSize )
49 Linux_Scale& getTest()
51 return reinterpret_cast<Linux_Scale&>( m_Pool.m_Test );
54 virtual void init() { cds::threading::Manager::attachThread() ; }
55 virtual void fini() { cds::threading::Manager::detachThread() ; }
59 for ( size_t i = 0; i < s_nPassPerThread; ++i ) {
60 typename ALLOC::value_type * p = m_Alloc.allocate( m_nSize / sizeof( typename ALLOC::value_type ), nullptr );
61 CPPUNIT_ASSERT( p != nullptr );
63 memset( p, 0, m_nSize );
66 memset( ((char *)p) + m_nSize * sizeof(*p) - 16, 0, 16 );
68 CPPUNIT_ASSERT( (reinterpret_cast<uintptr_t>(p) & (ALLOC::alignment - 1)) == 0 );
69 m_Alloc.deallocate( p, 1 );
74 template <class ALLOC>
75 void test( size_t nThreadCount, size_t nSize )
81 CPPUNIT_MSG( " Block size=" << nSize );
82 s_nPassPerThread = s_nPassCount / nThreadCount;
84 CppUnitMini::ThreadPool pool( *this );
85 pool.add( new Thread<ALLOC>( pool, alloc, nSize ), nThreadCount );
87 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
90 template <class ALLOC>
91 void test( size_t nThreadCount )
93 CPPUNIT_MSG( "Thread count=" << nThreadCount );
94 for ( size_t sz = 1; sz < s_nMaxBlockSize; sz *= 2 ) {
95 test<ALLOC>( nThreadCount, sz );
99 template <class ALLOC>
100 void test( bool bStat )
102 for ( size_t nThreadCount = 1; nThreadCount <= s_nMaxThreadCount; nThreadCount *= 2 ) {
103 summary_stat stBegin;
105 ALLOC::stat(stBegin);
107 test<ALLOC>( nThreadCount );
111 ALLOC::stat( stEnd );
113 std::cout << "\nStatistics:\n"
116 std::cout << "\nDelta statistics:\n"
122 void setUpParams( const CppUnitMini::TestCfg& cfg )
124 s_nPassCount = cfg.getULong( "PassCount", 10000000 );
125 s_nMaxBlockSize = cfg.getULong( "MaxBlockSize", 64 * 1024 - 16 );
126 s_nMaxThreadCount = cfg.getUInt( "MaxThreadCount", 64 );
127 if ( s_nMaxThreadCount == 0 )
128 s_nMaxThreadCount = cds::OS::topology::processor_count() * 2;
131 typedef MichaelAlignHeap_Stat<char, 64> t_MichaelAlignHeap_Stat;
132 typedef MichaelAlignHeap_NoStat<char,64> t_MichaelAlignHeap_NoStat;
133 typedef system_aligned_allocator<char, 64> t_system_aligned_allocator;
135 TEST_ALLOC_STAT( michael_heap_stat, MichaelHeap_Stat<char> )
136 TEST_ALLOC( michael_heap_nostat, MichaelHeap_NoStat<char> )
137 TEST_ALLOC( std_alloc, std_allocator<char> )
139 TEST_ALLOC_STAT( michael_alignheap_stat, t_MichaelAlignHeap_Stat )
140 TEST_ALLOC( michael_alignheap_nostat, t_MichaelAlignHeap_NoStat )
141 TEST_ALLOC( system_aligned_alloc, t_system_aligned_allocator )
143 CPPUNIT_TEST_SUITE( Linux_Scale )
144 CPPUNIT_TEST( michael_heap_nostat )
145 CPPUNIT_TEST( michael_heap_stat )
146 CPPUNIT_TEST( std_alloc )
148 CPPUNIT_TEST( system_aligned_alloc )
149 CPPUNIT_TEST( michael_alignheap_stat )
150 CPPUNIT_TEST( michael_alignheap_nostat )
151 CPPUNIT_TEST_SUITE_END();
154 } // namespace memory
155 CPPUNIT_TEST_SUITE_REGISTRATION( memory::Linux_Scale );