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]);
216 for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
217 for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
218 gp = rSet.extract( arrString[nItem % nArrSize]);
230 template <typename RCU, class Set>
231 class Extractor<cds::urcu::gc<RCU>, Set >: public CppUnitMini::TestThread
235 virtual Extractor * clone()
237 return new Extractor( *this );
240 size_t m_nDeleteSuccess;
241 size_t m_nDeleteFailed;
244 Extractor( CppUnitMini::ThreadPool& pool, Set& rSet )
245 : CppUnitMini::TestThread( pool )
248 Extractor( Extractor& src )
249 : CppUnitMini::TestThread( src )
253 Set_InsDel_string& getTest()
255 return reinterpret_cast<Set_InsDel_string&>( m_Pool.m_Test );
258 virtual void init() { cds::threading::Manager::attachThread() ; }
259 virtual void fini() { cds::threading::Manager::detachThread() ; }
268 typename Set::exempt_ptr xp;
270 const std::vector<std::string>& arrString = *getTest().m_parrString;
271 size_t nArrSize = arrString.size();
273 if ( m_nThreadNo & 1 ) {
274 for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
275 for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
276 if ( Set::c_bExtractLockExternal ) {
278 typename Set::rcu_lock l;
279 xp = rSet.extract( arrString[nItem % nArrSize] );
287 xp = rSet.extract( arrString[nItem % nArrSize] );
298 for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
299 for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
300 if ( Set::c_bExtractLockExternal ) {
302 typename Set::rcu_lock l;
303 xp = rSet.extract( arrString[nItem % nArrSize] );
311 xp = rSet.extract( arrString[nItem % nArrSize] );
327 void do_test( size_t nLoadFactor )
329 CPPUNIT_MSG( "Load factor=" << nLoadFactor );
331 Set testSet( c_nMapSize, nLoadFactor );
332 do_test_with( testSet );
336 void do_test_extract( size_t nLoadFactor )
338 CPPUNIT_MSG( "Load factor=" << nLoadFactor );
340 Set testSet( c_nMapSize, nLoadFactor );
341 do_test_extract_with( testSet );
345 void do_test_with( Set& testSet )
347 typedef Inserter<Set> InserterThread;
348 typedef Deleter<Set> DeleterThread;
349 cds::OS::Timer timer;
351 CppUnitMini::ThreadPool pool( *this );
352 pool.add( new InserterThread( pool, testSet ), c_nInsertThreadCount );
353 pool.add( new DeleterThread( pool, testSet ), c_nDeleteThreadCount );
355 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
357 size_t nInsertSuccess = 0;
358 size_t nInsertFailed = 0;
359 size_t nDeleteSuccess = 0;
360 size_t nDeleteFailed = 0;
361 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
362 InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
364 nInsertSuccess += pThread->m_nInsertSuccess;
365 nInsertFailed += pThread->m_nInsertFailed;
368 DeleterThread * p = static_cast<DeleterThread *>( *it );
369 nDeleteSuccess += p->m_nDeleteSuccess;
370 nDeleteFailed += p->m_nDeleteFailed;
374 CPPUNIT_MSG( " Totals: Ins succ=" << nInsertSuccess
375 << " Del succ=" << nDeleteSuccess << "\n"
376 << " : Ins fail=" << nInsertFailed
377 << " Del fail=" << nDeleteFailed
378 << " Set size=" << testSet.size()
382 CPPUNIT_MSG( " Clear set (single-threaded)..." );
384 for ( size_t i = 0; i < m_parrString->size(); ++i )
385 testSet.erase( (*m_parrString)[i] );
386 CPPUNIT_MSG( " Duration=" << timer.duration() );
387 CPPUNIT_ASSERT( testSet.empty() );
389 additional_check( testSet );
390 print_stat( testSet );
391 additional_cleanup( testSet );
395 void do_test_extract_with( Set& testSet )
397 typedef Inserter<Set> InserterThread;
398 typedef Deleter<Set> DeleterThread;
399 typedef Extractor<typename Set::gc, Set> ExtractThread;
401 size_t nDelThreadCount = c_nDeleteThreadCount / 2;
403 CppUnitMini::ThreadPool pool( *this );
404 pool.add( new InserterThread( pool, testSet ), c_nInsertThreadCount );
405 pool.add( new DeleterThread( pool, testSet ), nDelThreadCount );
406 pool.add( new ExtractThread( pool, testSet ), c_nDeleteThreadCount - nDelThreadCount );
408 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
410 size_t nInsertSuccess = 0;
411 size_t nInsertFailed = 0;
412 size_t nDeleteSuccess = 0;
413 size_t nDeleteFailed = 0;
414 size_t nExtractSuccess = 0;
415 size_t nExtractFailed = 0;
416 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
417 InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
419 nInsertSuccess += pThread->m_nInsertSuccess;
420 nInsertFailed += pThread->m_nInsertFailed;
423 DeleterThread * p = dynamic_cast<DeleterThread *>( *it );
425 nDeleteSuccess += p->m_nDeleteSuccess;
426 nDeleteFailed += p->m_nDeleteFailed;
429 ExtractThread * pExtract = dynamic_cast<ExtractThread *>( *it );
431 nExtractSuccess += pExtract->m_nDeleteSuccess;
432 nExtractFailed += pExtract->m_nDeleteFailed;
437 CPPUNIT_MSG( " Totals: Ins succ=" << nInsertSuccess
438 << " Del succ=" << nDeleteSuccess
439 << " Extract succ= " << nExtractSuccess << "\n"
440 << " : Ins fail=" << nInsertFailed
441 << " Del fail=" << nDeleteFailed
442 << " Extract fail=" << nExtractFailed
443 << " Set size=" << testSet.size()
447 CPPUNIT_MSG( " Clear set (single-threaded)..." );
448 cds::OS::Timer timer;
449 for ( size_t i = 0; i < m_parrString->size(); ++i )
450 testSet.erase( (*m_parrString)[i] );
451 CPPUNIT_MSG( " Duration=" << timer.duration() );
452 CPPUNIT_ASSERT( testSet.empty() );
454 additional_check( testSet );
455 print_stat( testSet );
456 additional_cleanup( testSet );
462 m_parrString = &CppUnitMini::TestCase::getTestStrings();
464 CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
465 << " delete=" << c_nDeleteThreadCount
466 << " pass count=" << c_nThreadPassCount
467 << " set size=" << c_nMapSize
470 for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
471 do_test<Set>( nLoadFactor );
472 if ( c_bPrintGCState )
480 m_parrString = &CppUnitMini::TestCase::getTestStrings();
482 CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
483 << " delete=" << c_nDeleteThreadCount
484 << " pass count=" << c_nThreadPassCount
485 << " set size=" << c_nMapSize
488 for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
489 do_test_extract<Set>( nLoadFactor );
490 if ( c_bPrintGCState )
498 m_parrString = &CppUnitMini::TestCase::getTestStrings();
500 CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
501 << " delete=" << c_nDeleteThreadCount
502 << " pass count=" << c_nThreadPassCount
503 << " set size=" << c_nMapSize
508 if ( c_bPrintGCState )
513 void test_nolf_extract()
515 m_parrString = &CppUnitMini::TestCase::getTestStrings();
517 CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
518 << " delete=" << c_nDeleteThreadCount
519 << " pass count=" << c_nThreadPassCount
520 << " set size=" << c_nMapSize
524 do_test_extract_with( s );
525 if ( c_bPrintGCState )
529 void setUpParams( const CppUnitMini::TestCfg& cfg ) {
530 c_nInsertThreadCount = cfg.getULong("InsertThreadCount", 4 );
531 c_nDeleteThreadCount = cfg.getULong("DeleteThreadCount", 4 );
532 c_nThreadPassCount = cfg.getULong("ThreadPassCount", 4 );
533 c_nMapSize = cfg.getULong("MapSize", 1000000 );
534 c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
535 c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
538 # include "set2/set_defs.h"
539 CDSUNIT_DECLARE_MichaelSet
540 CDSUNIT_DECLARE_SplitList
541 CDSUNIT_DECLARE_StripedSet
542 CDSUNIT_DECLARE_RefinableSet
543 CDSUNIT_DECLARE_CuckooSet
544 CDSUNIT_DECLARE_SkipListSet
545 CDSUNIT_DECLARE_EllenBinTreeSet
546 CDSUNIT_DECLARE_StdSet
548 CPPUNIT_TEST_SUITE_( Set_InsDel_string, "Map_InsDel_string" )
549 CDSUNIT_TEST_MichaelSet
550 CDSUNIT_TEST_SplitList
551 CDSUNIT_TEST_SkipListSet
552 CDSUNIT_TEST_EllenBinTreeSet
553 CDSUNIT_TEST_StripedSet
554 CDSUNIT_TEST_RefinableSet
555 CDSUNIT_TEST_CuckooSet
557 CPPUNIT_TEST_SUITE_END()
561 CPPUNIT_TEST_SUITE_REGISTRATION( Set_InsDel_string );