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 gp = rSet.extract( arrString[nItem % nArrSize]);
215 for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
216 for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
217 gp = rSet.extract( arrString[nItem % nArrSize]);
228 template <typename RCU, class Set>
229 class Extractor<cds::urcu::gc<RCU>, Set >: public CppUnitMini::TestThread
233 virtual Extractor * clone()
235 return new Extractor( *this );
238 size_t m_nDeleteSuccess;
239 size_t m_nDeleteFailed;
242 Extractor( CppUnitMini::ThreadPool& pool, Set& rSet )
243 : CppUnitMini::TestThread( pool )
246 Extractor( Extractor& src )
247 : CppUnitMini::TestThread( src )
251 Set_InsDel_string& getTest()
253 return reinterpret_cast<Set_InsDel_string&>( m_Pool.m_Test );
256 virtual void init() { cds::threading::Manager::attachThread() ; }
257 virtual void fini() { cds::threading::Manager::detachThread() ; }
266 typename Set::exempt_ptr xp;
268 const std::vector<std::string>& arrString = *getTest().m_parrString;
269 size_t nArrSize = arrString.size();
271 if ( m_nThreadNo & 1 ) {
272 for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
273 for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
274 if ( Set::c_bExtractLockExternal ) {
276 typename Set::rcu_lock l;
277 xp = rSet.extract( arrString[nItem % nArrSize] );
285 xp = rSet.extract( arrString[nItem % nArrSize] );
296 for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
297 for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
298 if ( Set::c_bExtractLockExternal ) {
300 typename Set::rcu_lock l;
301 xp = rSet.extract( arrString[nItem % nArrSize] );
309 xp = rSet.extract( arrString[nItem % nArrSize] );
325 void do_test( size_t nLoadFactor )
327 CPPUNIT_MSG( "Load factor=" << nLoadFactor );
329 Set testSet( c_nMapSize, nLoadFactor );
330 do_test_with( testSet );
334 void do_test_extract( size_t nLoadFactor )
336 CPPUNIT_MSG( "Load factor=" << nLoadFactor );
338 Set testSet( c_nMapSize, nLoadFactor );
339 do_test_extract_with( testSet );
343 void do_test_with( Set& testSet )
345 typedef Inserter<Set> InserterThread;
346 typedef Deleter<Set> DeleterThread;
347 cds::OS::Timer timer;
349 CppUnitMini::ThreadPool pool( *this );
350 pool.add( new InserterThread( pool, testSet ), c_nInsertThreadCount );
351 pool.add( new DeleterThread( pool, testSet ), c_nDeleteThreadCount );
353 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
355 size_t nInsertSuccess = 0;
356 size_t nInsertFailed = 0;
357 size_t nDeleteSuccess = 0;
358 size_t nDeleteFailed = 0;
359 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
360 InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
362 nInsertSuccess += pThread->m_nInsertSuccess;
363 nInsertFailed += pThread->m_nInsertFailed;
366 DeleterThread * p = static_cast<DeleterThread *>( *it );
367 nDeleteSuccess += p->m_nDeleteSuccess;
368 nDeleteFailed += p->m_nDeleteFailed;
372 CPPUNIT_MSG( " Totals: Ins succ=" << nInsertSuccess
373 << " Del succ=" << nDeleteSuccess << "\n"
374 << " : Ins fail=" << nInsertFailed
375 << " Del fail=" << nDeleteFailed
376 << " Set size=" << testSet.size()
380 CPPUNIT_MSG( " Clear set (single-threaded)..." );
382 for ( size_t i = 0; i < m_parrString->size(); ++i )
383 testSet.erase( (*m_parrString)[i] );
384 CPPUNIT_MSG( " Duration=" << timer.duration() );
385 CPPUNIT_ASSERT( testSet.empty() );
387 additional_check( testSet );
388 print_stat( testSet );
389 additional_cleanup( testSet );
393 void do_test_extract_with( Set& testSet )
395 typedef Inserter<Set> InserterThread;
396 typedef Deleter<Set> DeleterThread;
397 typedef Extractor<typename Set::gc, Set> ExtractThread;
399 size_t nDelThreadCount = c_nDeleteThreadCount / 2;
401 CppUnitMini::ThreadPool pool( *this );
402 pool.add( new InserterThread( pool, testSet ), c_nInsertThreadCount );
403 pool.add( new DeleterThread( pool, testSet ), nDelThreadCount );
404 pool.add( new ExtractThread( pool, testSet ), c_nDeleteThreadCount - nDelThreadCount );
406 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
408 size_t nInsertSuccess = 0;
409 size_t nInsertFailed = 0;
410 size_t nDeleteSuccess = 0;
411 size_t nDeleteFailed = 0;
412 size_t nExtractSuccess = 0;
413 size_t nExtractFailed = 0;
414 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
415 InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
417 nInsertSuccess += pThread->m_nInsertSuccess;
418 nInsertFailed += pThread->m_nInsertFailed;
421 DeleterThread * p = dynamic_cast<DeleterThread *>( *it );
423 nDeleteSuccess += p->m_nDeleteSuccess;
424 nDeleteFailed += p->m_nDeleteFailed;
427 ExtractThread * pExtract = dynamic_cast<ExtractThread *>( *it );
429 nExtractSuccess += pExtract->m_nDeleteSuccess;
430 nExtractFailed += pExtract->m_nDeleteFailed;
435 CPPUNIT_MSG( " Totals: Ins succ=" << nInsertSuccess
436 << " Del succ=" << nDeleteSuccess
437 << " Extract succ= " << nExtractSuccess << "\n"
438 << " : Ins fail=" << nInsertFailed
439 << " Del fail=" << nDeleteFailed
440 << " Extract fail=" << nExtractFailed
441 << " Set size=" << testSet.size()
445 CPPUNIT_MSG( " Clear set (single-threaded)..." );
446 cds::OS::Timer timer;
447 for ( size_t i = 0; i < m_parrString->size(); ++i )
448 testSet.erase( (*m_parrString)[i] );
449 CPPUNIT_MSG( " Duration=" << timer.duration() );
450 CPPUNIT_ASSERT( testSet.empty() );
452 additional_check( testSet );
453 print_stat( testSet );
454 additional_cleanup( testSet );
460 m_parrString = &CppUnitMini::TestCase::getTestStrings();
462 CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
463 << " delete=" << c_nDeleteThreadCount
464 << " pass count=" << c_nThreadPassCount
465 << " set size=" << c_nMapSize
468 for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
469 do_test<Set>( nLoadFactor );
470 if ( c_bPrintGCState )
478 m_parrString = &CppUnitMini::TestCase::getTestStrings();
480 CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
481 << " delete=" << c_nDeleteThreadCount
482 << " pass count=" << c_nThreadPassCount
483 << " set size=" << c_nMapSize
486 for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
487 do_test_extract<Set>( nLoadFactor );
488 if ( c_bPrintGCState )
496 m_parrString = &CppUnitMini::TestCase::getTestStrings();
498 CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
499 << " delete=" << c_nDeleteThreadCount
500 << " pass count=" << c_nThreadPassCount
501 << " set size=" << c_nMapSize
506 if ( c_bPrintGCState )
511 void test_nolf_extract()
513 m_parrString = &CppUnitMini::TestCase::getTestStrings();
515 CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
516 << " delete=" << c_nDeleteThreadCount
517 << " pass count=" << c_nThreadPassCount
518 << " set size=" << c_nMapSize
522 do_test_extract_with( s );
523 if ( c_bPrintGCState )
527 void setUpParams( const CppUnitMini::TestCfg& cfg ) {
528 c_nInsertThreadCount = cfg.getULong("InsertThreadCount", 4 );
529 c_nDeleteThreadCount = cfg.getULong("DeleteThreadCount", 4 );
530 c_nThreadPassCount = cfg.getULong("ThreadPassCount", 4 );
531 c_nMapSize = cfg.getULong("MapSize", 1000000 );
532 c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
533 c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
536 # include "set2/set_defs.h"
537 CDSUNIT_DECLARE_MichaelSet
538 CDSUNIT_DECLARE_SplitList
539 CDSUNIT_DECLARE_StripedSet
540 CDSUNIT_DECLARE_RefinableSet
541 CDSUNIT_DECLARE_CuckooSet
542 CDSUNIT_DECLARE_SkipListSet
543 CDSUNIT_DECLARE_EllenBinTreeSet
544 CDSUNIT_DECLARE_StdSet
546 CPPUNIT_TEST_SUITE_( Set_InsDel_string, "Map_InsDel_string" )
547 CDSUNIT_TEST_MichaelSet
548 CDSUNIT_TEST_SplitList
549 CDSUNIT_TEST_SkipListSet
550 CDSUNIT_TEST_EllenBinTreeSet
551 CDSUNIT_TEST_StripedSet
552 CDSUNIT_TEST_RefinableSet
553 CDSUNIT_TEST_CuckooSet
555 CPPUNIT_TEST_SUITE_END()
559 CPPUNIT_TEST_SUITE_REGISTRATION( Set_InsDel_string );