3 #include "set2/set_types.h"
4 #include "cppunit/thread.h"
10 # define TEST_SET(X) void X() { test<SetTypes<key_type, value_type>::X >(); }
11 # define TEST_SET_EXTRACT(X) void X() { test_extract<SetTypes<key_type, value_type>::X >(); }
12 # define TEST_SET_NOLF(X) void X() { test_nolf<SetTypes<key_type, value_type>::X >(); }
13 # define TEST_SET_NOLF_EXTRACT(X) void X() { test_nolf_extract<SetTypes<key_type, value_type>::X >(); }
16 static size_t c_nMapSize = 1000000 ; // set size
17 static size_t c_nInsertThreadCount = 4; // count of insertion thread
18 static size_t c_nDeleteThreadCount = 4; // count of deletion thread
19 static size_t c_nThreadPassCount = 4 ; // pass count for each thread
20 static size_t c_nMaxLoadFactor = 8 ; // maximum load factor
21 static bool c_bPrintGCState = true;
24 class Set_InsDel_string: public CppUnitMini::TestCase
26 typedef std::string key_type;
27 typedef size_t value_type;
29 const std::vector<std::string> * m_parrString;
32 class Inserter: public CppUnitMini::TestThread
35 typedef typename Set::value_type keyval_type;
37 virtual Inserter * clone()
39 return new Inserter( *this );
42 size_t m_nInsertSuccess;
43 size_t m_nInsertFailed;
46 Inserter( CppUnitMini::ThreadPool& pool, Set& rSet )
47 : CppUnitMini::TestThread( pool )
50 Inserter( Inserter& src )
51 : CppUnitMini::TestThread( src )
55 Set_InsDel_string& getTest()
57 return reinterpret_cast<Set_InsDel_string&>( m_Pool.m_Test );
60 virtual void init() { cds::threading::Manager::attachThread() ; }
61 virtual void fini() { cds::threading::Manager::detachThread() ; }
70 const std::vector<std::string>& arrString = *getTest().m_parrString;
71 size_t nArrSize = arrString.size();
73 if ( m_nThreadNo & 1 ) {
74 for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
75 for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
76 if ( rSet.insert( keyval_type(arrString[nItem % nArrSize], nItem * 8) ) )
84 for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
85 for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
86 if ( rSet.insert( keyval_type( arrString[nItem % nArrSize], nItem * 8) ) )
97 class Deleter: public CppUnitMini::TestThread
101 virtual Deleter * clone()
103 return new Deleter( *this );
106 size_t m_nDeleteSuccess;
107 size_t m_nDeleteFailed;
110 Deleter( CppUnitMini::ThreadPool& pool, Set& rSet )
111 : CppUnitMini::TestThread( pool )
114 Deleter( Deleter& src )
115 : CppUnitMini::TestThread( src )
119 Set_InsDel_string& getTest()
121 return reinterpret_cast<Set_InsDel_string&>( m_Pool.m_Test );
124 virtual void init() { cds::threading::Manager::attachThread() ; }
125 virtual void fini() { cds::threading::Manager::detachThread() ; }
134 const std::vector<std::string>& arrString = *getTest().m_parrString;
135 size_t nArrSize = arrString.size();
137 if ( m_nThreadNo & 1 ) {
138 for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
139 for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
140 if ( rSet.erase( arrString[nItem % nArrSize] ) )
148 for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
149 for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
150 if ( rSet.erase( arrString[nItem % nArrSize] ) )
160 template <typename GC, class Set>
161 class Extractor: public CppUnitMini::TestThread
165 virtual Extractor * clone()
167 return new Extractor( *this );
170 size_t m_nDeleteSuccess;
171 size_t m_nDeleteFailed;
174 Extractor( CppUnitMini::ThreadPool& pool, Set& rSet )
175 : CppUnitMini::TestThread( pool )
178 Extractor( Extractor& src )
179 : CppUnitMini::TestThread( src )
183 Set_InsDel_string& getTest()
185 return reinterpret_cast<Set_InsDel_string&>( m_Pool.m_Test );
188 virtual void init() { cds::threading::Manager::attachThread() ; }
189 virtual void fini() { cds::threading::Manager::detachThread() ; }
198 typename Set::guarded_ptr gp;
200 const std::vector<std::string>& arrString = *getTest().m_parrString;
201 size_t nArrSize = arrString.size();
203 if ( m_nThreadNo & 1 ) {
204 for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
205 for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
206 if ( rSet.extract( gp, arrString[nItem % nArrSize] ) )
214 for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
215 for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
216 if ( rSet.extract( gp, arrString[nItem % nArrSize] ) )
226 template <typename RCU, class Set>
227 class Extractor<cds::urcu::gc<RCU>, Set >: public CppUnitMini::TestThread
231 virtual Extractor * clone()
233 return new Extractor( *this );
236 size_t m_nDeleteSuccess;
237 size_t m_nDeleteFailed;
240 Extractor( CppUnitMini::ThreadPool& pool, Set& rSet )
241 : CppUnitMini::TestThread( pool )
244 Extractor( Extractor& src )
245 : CppUnitMini::TestThread( src )
249 Set_InsDel_string& getTest()
251 return reinterpret_cast<Set_InsDel_string&>( m_Pool.m_Test );
254 virtual void init() { cds::threading::Manager::attachThread() ; }
255 virtual void fini() { cds::threading::Manager::detachThread() ; }
264 typename Set::exempt_ptr xp;
266 const std::vector<std::string>& arrString = *getTest().m_parrString;
267 size_t nArrSize = arrString.size();
269 if ( m_nThreadNo & 1 ) {
270 for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
271 for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
272 if ( Set::c_bExtractLockExternal ) {
274 typename Set::rcu_lock l;
275 if ( rSet.extract( xp, arrString[nItem % nArrSize] ) )
283 if ( rSet.extract( xp, arrString[nItem % nArrSize] ) ) {
294 for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
295 for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
296 if ( Set::c_bExtractLockExternal ) {
298 typename Set::rcu_lock l;
299 if ( rSet.extract( xp, arrString[nItem % nArrSize] ) )
307 if ( rSet.extract( xp, arrString[nItem % nArrSize] ) ) {
323 void do_test( size_t nLoadFactor )
325 CPPUNIT_MSG( "Load factor=" << nLoadFactor );
327 Set testSet( c_nMapSize, nLoadFactor );
328 do_test_with( testSet );
332 void do_test_extract( size_t nLoadFactor )
334 CPPUNIT_MSG( "Load factor=" << nLoadFactor );
336 Set testSet( c_nMapSize, nLoadFactor );
337 do_test_extract_with( testSet );
341 void do_test_with( Set& testSet )
343 typedef Inserter<Set> InserterThread;
344 typedef Deleter<Set> DeleterThread;
345 cds::OS::Timer timer;
347 CppUnitMini::ThreadPool pool( *this );
348 pool.add( new InserterThread( pool, testSet ), c_nInsertThreadCount );
349 pool.add( new DeleterThread( pool, testSet ), c_nDeleteThreadCount );
351 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
353 size_t nInsertSuccess = 0;
354 size_t nInsertFailed = 0;
355 size_t nDeleteSuccess = 0;
356 size_t nDeleteFailed = 0;
357 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
358 InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
360 nInsertSuccess += pThread->m_nInsertSuccess;
361 nInsertFailed += pThread->m_nInsertFailed;
364 DeleterThread * p = static_cast<DeleterThread *>( *it );
365 nDeleteSuccess += p->m_nDeleteSuccess;
366 nDeleteFailed += p->m_nDeleteFailed;
370 CPPUNIT_MSG( " Totals: Ins succ=" << nInsertSuccess
371 << " Del succ=" << nDeleteSuccess << "\n"
372 << " : Ins fail=" << nInsertFailed
373 << " Del fail=" << nDeleteFailed
374 << " Set size=" << testSet.size()
378 CPPUNIT_MSG( " Clear set (single-threaded)..." );
380 for ( size_t i = 0; i < m_parrString->size(); ++i )
381 testSet.erase( (*m_parrString)[i] );
382 CPPUNIT_MSG( " Duration=" << timer.duration() );
383 CPPUNIT_ASSERT( testSet.empty() );
385 additional_check( testSet );
386 print_stat( testSet );
387 additional_cleanup( testSet );
391 void do_test_extract_with( Set& testSet )
393 typedef Inserter<Set> InserterThread;
394 typedef Deleter<Set> DeleterThread;
395 typedef Extractor<typename Set::gc, Set> ExtractThread;
397 size_t nDelThreadCount = c_nDeleteThreadCount / 2;
399 CppUnitMini::ThreadPool pool( *this );
400 pool.add( new InserterThread( pool, testSet ), c_nInsertThreadCount );
401 pool.add( new DeleterThread( pool, testSet ), nDelThreadCount );
402 pool.add( new ExtractThread( pool, testSet ), c_nDeleteThreadCount - nDelThreadCount );
404 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
406 size_t nInsertSuccess = 0;
407 size_t nInsertFailed = 0;
408 size_t nDeleteSuccess = 0;
409 size_t nDeleteFailed = 0;
410 size_t nExtractSuccess = 0;
411 size_t nExtractFailed = 0;
412 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
413 InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
415 nInsertSuccess += pThread->m_nInsertSuccess;
416 nInsertFailed += pThread->m_nInsertFailed;
419 DeleterThread * p = dynamic_cast<DeleterThread *>( *it );
421 nDeleteSuccess += p->m_nDeleteSuccess;
422 nDeleteFailed += p->m_nDeleteFailed;
425 ExtractThread * pExtract = dynamic_cast<ExtractThread *>( *it );
427 nExtractSuccess += pExtract->m_nDeleteSuccess;
428 nExtractFailed += pExtract->m_nDeleteFailed;
433 CPPUNIT_MSG( " Totals: Ins succ=" << nInsertSuccess
434 << " Del succ=" << nDeleteSuccess
435 << " Extract succ= " << nExtractSuccess << "\n"
436 << " : Ins fail=" << nInsertFailed
437 << " Del fail=" << nDeleteFailed
438 << " Extract fail=" << nExtractFailed
439 << " Set size=" << testSet.size()
443 CPPUNIT_MSG( " Clear set (single-threaded)..." );
444 cds::OS::Timer timer;
445 for ( size_t i = 0; i < m_parrString->size(); ++i )
446 testSet.erase( (*m_parrString)[i] );
447 CPPUNIT_MSG( " Duration=" << timer.duration() );
448 CPPUNIT_ASSERT( testSet.empty() );
450 additional_check( testSet );
451 print_stat( testSet );
452 additional_cleanup( testSet );
458 m_parrString = &CppUnitMini::TestCase::getTestStrings();
460 CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
461 << " delete=" << c_nDeleteThreadCount
462 << " pass count=" << c_nThreadPassCount
463 << " set size=" << c_nMapSize
466 for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
467 do_test<Set>( nLoadFactor );
468 if ( c_bPrintGCState )
476 m_parrString = &CppUnitMini::TestCase::getTestStrings();
478 CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
479 << " delete=" << c_nDeleteThreadCount
480 << " pass count=" << c_nThreadPassCount
481 << " set size=" << c_nMapSize
484 for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
485 do_test_extract<Set>( nLoadFactor );
486 if ( c_bPrintGCState )
494 m_parrString = &CppUnitMini::TestCase::getTestStrings();
496 CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
497 << " delete=" << c_nDeleteThreadCount
498 << " pass count=" << c_nThreadPassCount
499 << " set size=" << c_nMapSize
504 if ( c_bPrintGCState )
509 void test_nolf_extract()
511 m_parrString = &CppUnitMini::TestCase::getTestStrings();
513 CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
514 << " delete=" << c_nDeleteThreadCount
515 << " pass count=" << c_nThreadPassCount
516 << " set size=" << c_nMapSize
520 do_test_extract_with( s );
521 if ( c_bPrintGCState )
525 void setUpParams( const CppUnitMini::TestCfg& cfg ) {
526 c_nInsertThreadCount = cfg.getULong("InsertThreadCount", 4 );
527 c_nDeleteThreadCount = cfg.getULong("DeleteThreadCount", 4 );
528 c_nThreadPassCount = cfg.getULong("ThreadPassCount", 4 );
529 c_nMapSize = cfg.getULong("MapSize", 1000000 );
530 c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
531 c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
534 # include "set2/set_defs.h"
535 CDSUNIT_DECLARE_MichaelSet
536 CDSUNIT_DECLARE_SplitList
537 CDSUNIT_DECLARE_StripedSet
538 CDSUNIT_DECLARE_RefinableSet
539 CDSUNIT_DECLARE_CuckooSet
540 CDSUNIT_DECLARE_SkipListSet
541 CDSUNIT_DECLARE_EllenBinTreeSet
542 CDSUNIT_DECLARE_StdSet
544 CPPUNIT_TEST_SUITE_( Set_InsDel_string, "Map_InsDel_string" )
545 CDSUNIT_TEST_MichaelSet
546 CDSUNIT_TEST_SplitList
547 CDSUNIT_TEST_SkipListSet
548 CDSUNIT_TEST_EllenBinTreeSet
549 CDSUNIT_TEST_StripedSet
550 CDSUNIT_TEST_RefinableSet
551 CDSUNIT_TEST_CuckooSet
553 CPPUNIT_TEST_SUITE_END()
557 CPPUNIT_TEST_SUITE_REGISTRATION( Set_InsDel_string );