3 #include "set2/set_type.h"
4 #include "cppunit/thread.h"
5 #include <algorithm> // random_shuffle
9 # define TEST_SET(IMPL, C, X) void C::X() { test<set_type<IMPL, key_type, value_type>::X >() ; }
10 # define TEST_SET_EXTRACT(IMPL, C, X) TEST_SET(IMPL, C, X)
11 # define TEST_SET_NOLF(IMPL, C, X) void C::X() { test_nolf<set_type<IMPL, key_type, value_type>::X >() ; }
12 # define TEST_SET_NOLF_EXTRACT(IMPL, C, X) TEST_SET_NOLF(IMPL, C, X)
14 class Set_InsDelFind: public CppUnitMini::TestCase
16 static size_t c_nInitialMapSize; // initial map size
17 static size_t c_nThreadCount; // thread count
18 static size_t c_nMaxLoadFactor; // maximum load factor
19 static unsigned int c_nInsertPercentage;
20 static unsigned int c_nDeletePercentage;
21 static unsigned int c_nDuration; // test duration, seconds
22 static bool c_bPrintGCState;
31 static const unsigned int c_nShuffleSize = 100;
32 actions m_arrShuffle[c_nShuffleSize];
35 typedef CppUnitMini::TestCase Base;
36 typedef size_t key_type;
37 typedef size_t value_type;
40 class WorkThread: public CppUnitMini::TestThread
44 virtual WorkThread * clone()
46 return new WorkThread( *this );
49 size_t m_nInsertSuccess;
50 size_t m_nInsertFailed;
51 size_t m_nDeleteSuccess;
52 size_t m_nDeleteFailed;
53 size_t m_nFindSuccess;
57 WorkThread( CppUnitMini::ThreadPool& pool, Set& rMap )
58 : CppUnitMini::TestThread( pool )
61 WorkThread( WorkThread& src )
62 : CppUnitMini::TestThread( src )
66 Set_InsDelFind& getTest()
68 return reinterpret_cast<Set_InsDelFind&>( m_Pool.m_Test );
71 virtual void init() { cds::threading::Manager::attachThread() ; }
72 virtual void fini() { cds::threading::Manager::detachThread() ; }
85 actions * pAct = getTest().m_arrShuffle;
87 size_t const nNormalize = size_t(-1) / (c_nInitialMapSize * 2);
90 while ( !time_elapsed() ) {
91 nRand = cds::bitop::RandXorShift(nRand);
92 size_t n = nRand / nNormalize;
101 if ( rMap.insert( n ))
107 if ( rMap.erase( n ))
114 if ( ++i >= c_nShuffleSize )
122 void do_test( size_t nLoadFactor )
124 CPPUNIT_MSG( "Load factor=" << nLoadFactor );
126 Set testSet( c_nInitialMapSize, nLoadFactor );
127 do_test_with( testSet );
131 void do_test_with( Set& testSet )
133 typedef WorkThread<Set> work_thread;
135 // fill map - only odd number
137 size_t * pInitArr = new size_t[ c_nInitialMapSize ];
138 size_t * pEnd = pInitArr + c_nInitialMapSize;
139 for ( size_t i = 0; i < c_nInitialMapSize; ++i )
140 pInitArr[i] = i * 2 + 1;
141 std::random_shuffle( pInitArr, pEnd );
142 for ( size_t * p = pInitArr; p < pEnd; ++p )
143 testSet.insert( typename Set::value_type( *p, *p ) );
147 cds::OS::Timer timer;
149 CppUnitMini::ThreadPool pool( *this );
150 pool.add( new work_thread( pool, testSet ), c_nThreadCount );
151 pool.run( c_nDuration );
152 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
154 size_t nInsertSuccess = 0;
155 size_t nInsertFailed = 0;
156 size_t nDeleteSuccess = 0;
157 size_t nDeleteFailed = 0;
158 size_t nFindSuccess = 0;
159 size_t nFindFailed = 0;
160 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
161 work_thread * pThread = static_cast<work_thread *>( *it );
162 assert( pThread != nullptr );
163 nInsertSuccess += pThread->m_nInsertSuccess;
164 nInsertFailed += pThread->m_nInsertFailed;
165 nDeleteSuccess += pThread->m_nDeleteSuccess;
166 nDeleteFailed += pThread->m_nDeleteFailed;
167 nFindSuccess += pThread->m_nFindSuccess;
168 nFindFailed += pThread->m_nFindFailed;
171 size_t nTotalOps = nInsertSuccess + nInsertFailed + nDeleteSuccess + nDeleteFailed + nFindSuccess + nFindFailed;
173 CPPUNIT_MSG( " Totals (success/failed): \n\t"
174 << " Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
175 << " Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
176 << " Find=" << nFindSuccess << '/' << nFindFailed << "\n\t"
177 << " Speed=" << (nFindSuccess + nFindFailed) / c_nDuration << " find/sec\n\t"
178 << " " << (nInsertSuccess + nDeleteSuccess) / c_nDuration << " modify/sec\n\t"
179 << " Total ops=" << nTotalOps << "\n\t"
180 << " speed=" << nTotalOps / c_nDuration << " ops/sec\n\t"
181 << " Set size=" << testSet.size()
185 CPPUNIT_MSG( " Clear map (single-threaded)..." );
188 CPPUNIT_MSG( " Duration=" << timer.duration() );
189 CPPUNIT_CHECK_EX( testSet.empty(), ((long long) testSet.size()) );
191 additional_check( testSet );
192 print_stat( testSet );
193 additional_cleanup( testSet );
199 CPPUNIT_MSG( "Thread count=" << c_nThreadCount
200 << " initial map size=" << c_nInitialMapSize
201 << " insert=" << c_nInsertPercentage << '%'
202 << " delete=" << c_nDeletePercentage << '%'
203 << " duration=" << c_nDuration << "s"
206 for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
207 do_test<Set>( nLoadFactor );
208 if ( c_bPrintGCState )
216 CPPUNIT_MSG( "Thread count=" << c_nThreadCount
217 << " initial map size=" << c_nInitialMapSize
218 << " insert=" << c_nInsertPercentage << '%'
219 << " delete=" << c_nDeletePercentage << '%'
220 << " duration=" << c_nDuration << "s"
225 //CPPUNIT_MSG( s.statistics() );
226 if ( c_bPrintGCState )
230 void setUpParams( const CppUnitMini::TestCfg& cfg );
232 void run_MichaelSet(const char *in_name, bool invert = false);
233 void run_SplitList(const char *in_name, bool invert = false);
234 void run_SkipListSet(const char *in_name, bool invert = false);
235 void run_CuckooSet(const char *in_name, bool invert = false);
236 void run_StripedSet(const char *in_name, bool invert = false);
237 void run_RefinableSet(const char *in_name, bool invert = false);
238 void run_EllenBinTreeSet(const char *in_name, bool invert = false);
239 void run_StdSet(const char *in_name, bool invert = false);
241 virtual void myRun(const char *in_name, bool invert = false);
243 # include "set2/set_defs.h"
244 CDSUNIT_DECLARE_MichaelSet
245 CDSUNIT_DECLARE_SplitList
246 CDSUNIT_DECLARE_StripedSet
247 CDSUNIT_DECLARE_RefinableSet
248 CDSUNIT_DECLARE_CuckooSet
249 CDSUNIT_DECLARE_SkipListSet
250 CDSUNIT_DECLARE_EllenBinTreeSet
251 CDSUNIT_DECLARE_StdSet