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