2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "map2/map_type.h"
32 #include "cppunit/thread.h"
38 #define TEST_CASE(TAG, X) void X();
40 class Map_InsDel_Item_string: public CppUnitMini::TestCase
43 size_t c_nMapSize = 1000000; // map size
44 size_t c_nThreadCount = 4; // thread count
45 size_t c_nAttemptCount = 100000; // count of SUCCESS insert/delete for each thread
46 size_t c_nMaxLoadFactor = 8; // maximum load factor
47 bool c_bPrintGCState = true;
49 size_t c_nCuckooInitialSize = 1024; // initial size for CuckooMap
50 size_t c_nCuckooProbesetSize = 16; // CuckooMap probeset size (only for list-based probeset)
51 size_t c_nCuckooProbesetThreshold = 0; // CUckooMap probeset threshold (o - use default)
53 size_t c_nFeldmanMap_HeadBits = 10;
54 size_t c_nFeldmanMap_ArrayBits = 4;
57 size_t c_nLoadFactor = 2; // current load factor
60 typedef std::string key_type;
61 typedef size_t value_type;
63 const std::vector<std::string> * m_parrString;
66 class Inserter: public CppUnitMini::TestThread
70 virtual Inserter * clone()
72 return new Inserter( *this );
75 size_t m_nInsertSuccess;
76 size_t m_nInsertFailed;
79 Inserter( CppUnitMini::ThreadPool& pool, Map& rMap )
80 : CppUnitMini::TestThread( pool )
83 Inserter( Inserter& src )
84 : CppUnitMini::TestThread( src )
88 Map_InsDel_Item_string& getTest()
90 return reinterpret_cast<Map_InsDel_Item_string&>( m_Pool.m_Test );
93 virtual void init() { cds::threading::Manager::attachThread() ; }
94 virtual void fini() { cds::threading::Manager::detachThread() ; }
103 size_t nGoalItem = getTest().c_nGoalItem;
104 std::string strGoal = (*getTest().m_parrString)[nGoalItem];
105 size_t const nAttemptCount = getTest().c_nAttemptCount;
107 for ( size_t nAttempt = 0; nAttempt < nAttemptCount; ) {
108 if ( rMap.insert( strGoal, nGoalItem )) {
119 class Deleter: public CppUnitMini::TestThread
123 struct erase_cleaner {
124 void operator ()(std::pair<typename Map::key_type const, typename Map::mapped_type>& val )
128 // for boost::container::flat_map
129 void operator ()(std::pair< typename std::remove_const< typename Map::key_type >::type, typename Map::mapped_type>& val )
133 // for BronsonAVLTreeMap
134 void operator()( typename Map::key_type const& /*key*/, typename Map::mapped_type& val )
140 virtual Deleter * clone()
142 return new Deleter( *this );
145 size_t m_nDeleteSuccess;
146 size_t m_nDeleteFailed;
149 Deleter( CppUnitMini::ThreadPool& pool, Map& rMap )
150 : CppUnitMini::TestThread( pool )
153 Deleter( Deleter& src )
154 : CppUnitMini::TestThread( src )
158 Map_InsDel_Item_string& getTest()
160 return reinterpret_cast<Map_InsDel_Item_string&>( m_Pool.m_Test );
163 virtual void init() { cds::threading::Manager::attachThread() ; }
164 virtual void fini() { cds::threading::Manager::detachThread() ; }
173 size_t nGoalItem = getTest().c_nGoalItem;
174 std::string strGoal = (*getTest().m_parrString)[nGoalItem];
175 size_t const nAttemptCount = getTest().c_nAttemptCount;
177 for ( size_t nAttempt = 0; nAttempt < nAttemptCount; ) {
178 if ( rMap.erase( strGoal, erase_cleaner() )) {
191 void do_test( Map& testMap )
193 typedef Inserter<Map> InserterThread;
194 typedef Deleter<Map> DeleterThread;
195 cds::OS::Timer timer;
198 CPPUNIT_MSG( " Fill map (" << c_nMapSize << " items)...");
200 for ( size_t i = 0; i < c_nMapSize; ++i ) {
201 CPPUNIT_ASSERT_EX( testMap.insert( (*m_parrString)[i], i ), i );
203 CPPUNIT_MSG( " Duration=" << timer.duration() );
205 CPPUNIT_MSG( " Insert/delete the key " << c_nGoalItem << " (" << c_nAttemptCount << " successful times)...");
206 CppUnitMini::ThreadPool pool( *this );
207 pool.add( new InserterThread( pool, testMap ), (c_nThreadCount + 1) / 2 );
208 pool.add( new DeleterThread( pool, testMap ), (c_nThreadCount + 1) / 2 );
210 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
212 size_t nInsertSuccess = 0;
213 size_t nInsertFailed = 0;
214 size_t nDeleteSuccess = 0;
215 size_t nDeleteFailed = 0;
216 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
217 InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
219 CPPUNIT_CHECK( pThread->m_nInsertSuccess == c_nAttemptCount );
220 nInsertSuccess += pThread->m_nInsertSuccess;
221 nInsertFailed += pThread->m_nInsertFailed;
224 DeleterThread * p = static_cast<DeleterThread *>( *it );
225 CPPUNIT_CHECK( p->m_nDeleteSuccess == c_nAttemptCount );
226 nDeleteSuccess += p->m_nDeleteSuccess;
227 nDeleteFailed += p->m_nDeleteFailed;
230 CPPUNIT_CHECK_EX( nInsertSuccess == nDeleteSuccess, "nInsertSuccess=" << nInsertSuccess << ", nDeleteSuccess=" << nDeleteSuccess );
231 CPPUNIT_MSG( " Totals: Ins fail=" << nInsertFailed << " Del fail=" << nDeleteFailed );
233 // Check if the map contains all items
234 CPPUNIT_MSG( " Check if the map contains all items" );
236 for ( size_t i = 0; i < c_nMapSize; ++i ) {
237 CPPUNIT_CHECK_EX( testMap.contains( (*m_parrString)[i] ), "Key \"" << (*m_parrString)[i] << "\" not found" );
239 CPPUNIT_MSG( " Duration=" << timer.duration() );
241 check_before_cleanup( testMap );
244 additional_check( testMap );
245 print_stat( testMap );
246 additional_cleanup( testMap );
252 m_parrString = &CppUnitMini::TestCase::getTestStrings();
253 if ( c_nMapSize > m_parrString->size() )
254 c_nMapSize = m_parrString->size();
255 if ( c_nGoalItem > m_parrString->size() )
256 c_nGoalItem = m_parrString->size() / 2;
258 CPPUNIT_MSG( "Thread count= " << c_nThreadCount
259 << " pass count=" << c_nAttemptCount
260 << " map size=" << c_nMapSize
263 if ( Map::c_bLoadFactorDepended ) {
264 for ( c_nLoadFactor = 1; c_nLoadFactor <= c_nMaxLoadFactor; c_nLoadFactor *= 2 ) {
265 CPPUNIT_MSG( "Load factor=" << c_nLoadFactor );
266 Map testMap( *this );
268 if ( c_bPrintGCState )
273 Map testMap( *this );
275 if ( c_bPrintGCState )
280 void setUpParams( const CppUnitMini::TestCfg& cfg );
282 # include "map2/map_defs.h"
283 CDSUNIT_DECLARE_MichaelMap
284 CDSUNIT_DECLARE_SplitList
285 CDSUNIT_DECLARE_SkipListMap
286 CDSUNIT_DECLARE_EllenBinTreeMap
287 CDSUNIT_DECLARE_BronsonAVLTreeMap
288 CDSUNIT_DECLARE_FeldmanHashMap_city
289 CDSUNIT_DECLARE_StripedMap
290 CDSUNIT_DECLARE_RefinableMap
291 CDSUNIT_DECLARE_CuckooMap
292 // CDSUNIT_DECLARE_StdMap // very slow!!
294 CPPUNIT_TEST_SUITE(Map_InsDel_Item_string)
295 CDSUNIT_TEST_MichaelMap
296 CDSUNIT_TEST_SplitList
297 CDSUNIT_TEST_SkipListMap
298 CDSUNIT_TEST_EllenBinTreeMap
299 CDSUNIT_TEST_BronsonAVLTreeMap
300 CDSUNIT_TEST_FeldmanHashMap_city
301 CDSUNIT_TEST_CuckooMap
302 CDSUNIT_TEST_StripedMap
303 CDSUNIT_TEST_RefinableMap
304 // CDSUNIT_TEST_StdMap // very slow!!
305 CPPUNIT_TEST_SUITE_END();