3 // defines concurrent access to map::nonconcurrent_iterator::Sequence::TValue::nAccess field
5 #include "map2/map_types.h"
6 #include "cppunit/thread.h"
10 // find int test in map<int> in mutithreaded mode
13 # define TEST_MAP(X) void X() { test<MapTypes<key_type, value_type>::X >() ; }
14 # define TEST_MAP_NOLF(X) void X() { test_nolf<MapTypes<key_type, value_type>::X >() ; }
15 # define TEST_MAP_EXTRACT(X) TEST_MAP(X)
16 # define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
19 static size_t c_nThreadCount = 8 ; // thread count
20 static size_t c_nMapSize = 20000000 ; // map size (count of searching item)
21 static size_t c_nPercentExists = 50 ; // percent of existing keys in searching sequence
22 static size_t c_nPassCount = 2;
23 static size_t c_nMaxLoadFactor = 8 ; // maximum load factor
24 static bool c_bPrintGCState = true;
27 class Map_find_string: public CppUnitMini::TestCase
29 typedef std::string key_type;
31 std::string const * pKey;
32 bool bExists ; // true - key in map, false - key not in map
35 typedef std::vector<value_type> ValueVector;
37 size_t m_nRealMapSize;
41 class TestThread: public CppUnitMini::TestThread
45 virtual TestThread * clone()
47 return new TestThread( *this );
64 TestThread( CppUnitMini::ThreadPool& pool, MAP& rMap )
65 : CppUnitMini::TestThread( pool )
68 TestThread( TestThread& src )
69 : CppUnitMini::TestThread( src )
73 Map_find_string& getTest()
75 return reinterpret_cast<Map_find_string&>( m_Pool.m_Test );
78 virtual void init() { cds::threading::Manager::attachThread() ; }
79 virtual void fini() { cds::threading::Manager::detachThread() ; }
83 ValueVector& arr = getTest().m_Arr;
84 //size_t nSize = arr.size();
87 for ( size_t nPass = 0; nPass < c_nPassCount; ++nPass ) {
88 if ( m_nThreadNo & 1 ) {
89 ValueVector::const_iterator itEnd = arr.end();
90 for ( ValueVector::const_iterator it = arr.begin(); it != itEnd; ++it ) {
91 bool bFound = rMap.find( *(it->pKey) );
94 ++m_KeyExists.nSuccess;
96 ++m_KeyExists.nFailed;
100 ++m_KeyNotExists.nFailed;
102 ++m_KeyNotExists.nSuccess;
107 ValueVector::const_reverse_iterator itEnd = arr.rend();
108 for ( ValueVector::const_reverse_iterator it = arr.rbegin(); it != itEnd; ++it ) {
109 bool bFound = rMap.find( *(it->pKey) );
112 ++m_KeyExists.nSuccess;
114 ++m_KeyExists.nFailed;
118 ++m_KeyNotExists.nFailed;
120 ++m_KeyNotExists.nSuccess;
130 : m_bSeqInit( false )
135 void generateSequence()
137 size_t nPercent = c_nPercentExists;
139 if ( nPercent > 100 )
141 else if ( nPercent < 1 )
146 std::vector<std::string> const & arrString = CppUnitMini::TestCase::getTestStrings();
147 size_t nSize = arrString.size();
148 if ( nSize > c_nMapSize )
150 m_Arr.resize( nSize );
151 for ( size_t i = 0; i < nSize; ++i ) {
152 m_Arr[i].pKey = &( arrString[i] );
153 m_Arr[i].bExists = CppUnitMini::Rand( 100 ) <= nPercent;
154 if ( m_Arr[i].bExists )
161 void find_string_test( MAP& testMap )
163 typedef TestThread<MAP> Thread;
164 cds::OS::Timer timer;
167 CPPUNIT_MSG( " Fill map...");
169 for ( size_t i = 0; i < m_Arr.size(); ++i ) {
170 // Âñå êëþ÷è â arrData - óíèêàëüíûå, ïîýòîìó îøèáîê ïðè âñòàâêå áûòü íå äîëæíî
171 if ( m_Arr[i].bExists )
172 CPPUNIT_ASSERT( testMap.insert( *(m_Arr[i].pKey), m_Arr[i] ) );
174 CPPUNIT_MSG( " Duration=" << timer.duration() );
176 CPPUNIT_MSG( " Searching...");
177 CppUnitMini::ThreadPool pool( *this );
178 pool.add( new Thread( pool, testMap ), c_nThreadCount );
180 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
182 // Ïðîâåðÿåì, ÷òî ó âñåõ threads ÷èñëî óñïåøíûõ ïîèñêîâ = ÷èñëó ýëåìåíòîâ â map
183 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
184 Thread * pThread = static_cast<Thread *>( *it );
185 CPPUNIT_ASSERT( pThread->m_KeyExists.nSuccess == m_nRealMapSize * c_nPassCount );
186 CPPUNIT_ASSERT( pThread->m_KeyExists.nFailed == 0 );
187 CPPUNIT_ASSERT( pThread->m_KeyNotExists.nSuccess == (m_Arr.size() - m_nRealMapSize) * c_nPassCount );
188 CPPUNIT_ASSERT( pThread->m_KeyNotExists.nFailed == 0 );
192 additional_check( testMap );
193 print_stat( testMap );
194 additional_cleanup( testMap );
197 void initTestSequence()
202 CPPUNIT_MSG( "Generating test data...");
203 cds::OS::Timer timer;
205 CPPUNIT_MSG( " Duration=" << timer.duration() );
206 CPPUNIT_MSG( "Map size=" << m_nRealMapSize << " find key loop=" << m_Arr.size() << " (" << c_nPercentExists << "% success)" );
207 CPPUNIT_MSG( "Thread count=" << c_nThreadCount << " Pass count=" << c_nPassCount );
216 for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
217 CPPUNIT_MSG( "Load factor=" << nLoadFactor );
218 MAP testMap( m_Arr.size(), nLoadFactor );
219 find_string_test( testMap );
220 if ( c_bPrintGCState )
231 find_string_test( testMap );
232 if ( c_bPrintGCState )
236 void setUpParams( const CppUnitMini::TestCfg& cfg ) {
237 c_nThreadCount = cfg.getULong("ThreadCount", 8 ) ; // thread count
238 c_nMapSize = cfg.getULong("MapSize", 20000000 ) ; // map size (count of searching item)
239 c_nPercentExists = cfg.getULong("PercentExists", 50 ) ; // percent of existing keys in searching sequence
240 c_nPassCount = cfg.getULong("PassCount", 2 );
241 c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
242 c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
245 # include "map2/map_defs.h"
246 CDSUNIT_DECLARE_MichaelMap
247 CDSUNIT_DECLARE_MichaelMap_nogc
248 CDSUNIT_DECLARE_SplitList
249 CDSUNIT_DECLARE_SplitList_nogc
250 CDSUNIT_DECLARE_SkipListMap
251 CDSUNIT_DECLARE_SkipListMap_nogc
252 CDSUNIT_DECLARE_EllenBinTreeMap
253 CDSUNIT_DECLARE_StripedMap
254 CDSUNIT_DECLARE_RefinableMap
255 CDSUNIT_DECLARE_CuckooMap
256 CDSUNIT_DECLARE_StdMap
258 CPPUNIT_TEST_SUITE( Map_find_string )
259 CDSUNIT_TEST_MichaelMap
260 CDSUNIT_TEST_MichaelMap_nogc
261 CDSUNIT_TEST_SplitList
262 CDSUNIT_TEST_SplitList_nogc
263 CDSUNIT_TEST_SkipListMap
264 CDSUNIT_TEST_SkipListMap_nogc
265 CDSUNIT_TEST_EllenBinTreeMap
266 CDSUNIT_TEST_StripedMap
267 CDSUNIT_TEST_RefinableMap
268 CDSUNIT_TEST_CuckooMap
270 CPPUNIT_TEST_SUITE_END()
274 CPPUNIT_TEST_SUITE_REGISTRATION( Map_find_string );