Refactored Set_InsDelFind MT-test
[libcds.git] / tests / unit / set2 / set_insdelfind.h
1 //$$CDS-header$$
2
3 #include "set2/set_type.h"
4 #include "cppunit/thread.h"
5
6 namespace set2 {
7
8 #define TEST_CASE(TAG, X)  void X();
9
10     class Set_InsDelFind: public CppUnitMini::TestCase
11     {
12     public:
13         size_t c_nSetSize = 500000;      // initial set size
14         size_t c_nThreadCount = 8;       // thread count
15         size_t c_nMaxLoadFactor = 8;     // maximum load factor
16         unsigned int c_nInsertPercentage = 5;
17         unsigned int c_nDeletePercentage = 5;
18         unsigned int c_nDuration = 30;   // test duration, seconds
19         bool c_bPrintGCState = true;
20
21         size_t  c_nCuckooInitialSize = 1024;// initial size for CuckooSet
22         size_t  c_nCuckooProbesetSize = 16; // CuckooSet probeset size (only for list-based probeset)
23         size_t  c_nCuckooProbesetThreshold = 0; // CUckooSet probeset threshold (0 - use default)
24
25         size_t c_nLoadFactor = 2;
26
27     public:
28         enum actions
29         {
30             do_find,
31             do_insert,
32             do_delete
33         };
34         static const unsigned int c_nShuffleSize = 100;
35         actions m_arrShuffle[c_nShuffleSize];
36
37     protected:
38         typedef CppUnitMini::TestCase Base;
39         typedef size_t  key_type;
40         typedef size_t  value_type;
41
42         template <class Set>
43         class WorkThread: public CppUnitMini::TestThread
44         {
45             Set&     m_Map;
46
47             virtual WorkThread *    clone()
48             {
49                 return new WorkThread( *this );
50             }
51         public:
52             size_t  m_nInsertSuccess;
53             size_t  m_nInsertFailed;
54             size_t  m_nDeleteSuccess;
55             size_t  m_nDeleteFailed;
56             size_t  m_nFindSuccess;
57             size_t  m_nFindFailed;
58
59         public:
60             WorkThread( CppUnitMini::ThreadPool& pool, Set& rMap )
61                 : CppUnitMini::TestThread( pool )
62                 , m_Map( rMap )
63             {}
64             WorkThread( WorkThread& src )
65                 : CppUnitMini::TestThread( src )
66                 , m_Map( src.m_Map )
67             {}
68
69             Set_InsDelFind&  getTest()
70             {
71                 return reinterpret_cast<Set_InsDelFind&>( m_Pool.m_Test );
72             }
73
74             virtual void init() { cds::threading::Manager::attachThread()   ; }
75             virtual void fini() { cds::threading::Manager::detachThread()   ; }
76
77             virtual void test()
78             {
79                 Set& rMap = m_Map;
80
81                 m_nInsertSuccess =
82                     m_nInsertFailed =
83                     m_nDeleteSuccess =
84                     m_nDeleteFailed =
85                     m_nFindSuccess =
86                     m_nFindFailed = 0;
87
88                 actions * pAct = getTest().m_arrShuffle;
89                 unsigned int i = 0;
90                 size_t const nNormalize = size_t(-1) / ( getTest().c_nSetSize * 2);
91
92                 size_t nRand = 0;
93                 while ( !time_elapsed() ) {
94                     nRand = cds::bitop::RandXorShift(nRand);
95                     size_t n = nRand / nNormalize;
96                     switch ( pAct[i] ) {
97                     case do_find:
98                         if ( rMap.contains( n ))
99                             ++m_nFindSuccess;
100                         else
101                             ++m_nFindFailed;
102                         break;
103                     case do_insert:
104                         if ( rMap.insert( n ))
105                             ++m_nInsertSuccess;
106                         else
107                             ++m_nInsertFailed;
108                         break;
109                     case do_delete:
110                         if ( rMap.erase( n ))
111                             ++m_nDeleteSuccess;
112                         else
113                             ++m_nDeleteFailed;
114                         break;
115                     }
116
117                     if ( ++i >= c_nShuffleSize )
118                         i = 0;
119                 }
120             }
121         };
122
123     protected:
124         template <class Set>
125         void do_test( Set& testSet )
126         {
127             typedef WorkThread<Set> work_thread;
128
129             // fill map - only odd number
130             {
131                 size_t * pInitArr = new size_t[ c_nSetSize ];
132                 size_t * pEnd = pInitArr + c_nSetSize;
133                 for ( size_t i = 0; i < c_nSetSize; ++i )
134                     pInitArr[i] = i * 2 + 1;
135                 shuffle( pInitArr, pEnd );
136                 for ( size_t * p = pInitArr; p < pEnd; ++p )
137                     testSet.insert( typename Set::value_type( *p, *p ) );
138                 delete [] pInitArr;
139             }
140
141             cds::OS::Timer    timer;
142
143             CppUnitMini::ThreadPool pool( *this );
144             pool.add( new work_thread( pool, testSet ), c_nThreadCount );
145             pool.run( c_nDuration );
146             CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
147
148             size_t nInsertSuccess = 0;
149             size_t nInsertFailed = 0;
150             size_t nDeleteSuccess = 0;
151             size_t nDeleteFailed = 0;
152             size_t nFindSuccess = 0;
153             size_t nFindFailed = 0;
154             for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
155                 work_thread * pThread = static_cast<work_thread *>( *it );
156                 assert( pThread != nullptr );
157                 nInsertSuccess += pThread->m_nInsertSuccess;
158                 nInsertFailed += pThread->m_nInsertFailed;
159                 nDeleteSuccess += pThread->m_nDeleteSuccess;
160                 nDeleteFailed += pThread->m_nDeleteFailed;
161                 nFindSuccess += pThread->m_nFindSuccess;
162                 nFindFailed += pThread->m_nFindFailed;
163             }
164
165             size_t nTotalOps = nInsertSuccess + nInsertFailed + nDeleteSuccess + nDeleteFailed + nFindSuccess + nFindFailed;
166
167             CPPUNIT_MSG( "  Totals (success/failed): \n\t"
168                       << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
169                       << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
170                       << "        Find=" << nFindSuccess   << '/' << nFindFailed   << "\n\t"
171                       << "       Speed=" << (nFindSuccess + nFindFailed) / c_nDuration << " find/sec\n\t"
172                       << "             " << (nInsertSuccess + nDeleteSuccess) / c_nDuration << " modify/sec\n\t"
173                       << "   Total ops=" << nTotalOps << "\n\t"
174                       << "       speed=" << nTotalOps / c_nDuration << " ops/sec\n\t"
175                       << "      Set size=" << testSet.size()
176                 );
177
178
179             CPPUNIT_MSG( "  Clear map (single-threaded)..." );
180             timer.reset();
181             testSet.clear();
182             CPPUNIT_MSG( "   Duration=" << timer.duration() );
183             CPPUNIT_CHECK_EX( testSet.empty(), ((long long) testSet.size()) );
184
185             additional_check( testSet );
186             print_stat( testSet );
187             additional_cleanup( testSet );
188         }
189
190         template <class Set>
191         void run_test()
192         {
193             CPPUNIT_MSG( "Thread count=" << c_nThreadCount
194                 << " initial map size=" << c_nSetSize
195                 << " insert=" << c_nInsertPercentage << '%'
196                 << " delete=" << c_nDeletePercentage << '%'
197                 << " duration=" << c_nDuration << "s"
198                 );
199
200             if ( Set::c_bLoadFactorDepended ) {
201                 for ( c_nLoadFactor = 1; c_nLoadFactor <= c_nMaxLoadFactor; c_nLoadFactor *= 2 ) {
202                     CPPUNIT_MSG("  LoadFactor = " << c_nLoadFactor );
203                     Set s( *this );
204                     do_test( s );
205                     if ( c_bPrintGCState )
206                         print_gc_state();
207                 }
208             }
209             else {
210                 Set s( *this );
211                 do_test( s );
212                 if ( c_bPrintGCState )
213                     print_gc_state();
214             }
215         }
216
217         void setUpParams( const CppUnitMini::TestCfg& cfg );
218
219 #   include "set2/set_defs.h"
220         CDSUNIT_DECLARE_MichaelSet
221         CDSUNIT_DECLARE_SplitList
222         CDSUNIT_DECLARE_StripedSet
223         CDSUNIT_DECLARE_RefinableSet
224         CDSUNIT_DECLARE_CuckooSet
225         CDSUNIT_DECLARE_SkipListSet
226         CDSUNIT_DECLARE_EllenBinTreeSet
227         CDSUNIT_DECLARE_MultiLevelHashSet
228         CDSUNIT_DECLARE_StdSet
229
230         CPPUNIT_TEST_SUITE_(Set_InsDelFind, "Map_InsDelFind")
231             CDSUNIT_TEST_MichaelSet
232             CDSUNIT_TEST_SplitList
233             CDSUNIT_TEST_SkipListSet
234             CDSUNIT_TEST_MultiLevelHashSet
235             CDSUNIT_TEST_EllenBinTreeSet
236             CDSUNIT_TEST_StripedSet
237             CDSUNIT_TEST_RefinableSet
238             CDSUNIT_TEST_CuckooSet
239             CDSUNIT_TEST_StdSet
240         CPPUNIT_TEST_SUITE_END();
241
242     };
243 } // namespace set2