From: khizmax <khizmax@gmail.com> Date: Mon, 23 Mar 2015 14:01:11 +0000 (+0300) Subject: Issue #21: splitted map_delodd test X-Git-Tag: v2.1.0~296^2~15 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=24097b648bf247c4feb9ab5e042f0b5355abb0ce;p=libcds.git Issue #21: splitted map_delodd test --- diff --git a/projects/Win/vc12/unit-map-delodd.vcxproj b/projects/Win/vc12/unit-map-delodd.vcxproj index 8474f43a..ec9b34a1 100644 --- a/projects/Win/vc12/unit-map-delodd.vcxproj +++ b/projects/Win/vc12/unit-map-delodd.vcxproj @@ -44,6 +44,15 @@ </ItemGroup> <ItemGroup> <ClCompile Include="..\..\..\tests\unit\map2\map_delodd.cpp" /> + <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_bronsonavltree.cpp" /> + <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_cuckoo.cpp" /> + <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_ellentree.cpp" /> + <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_michael.cpp" /> + <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_skip.cpp" /> + <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_split.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\..\..\tests\unit\map2\map_delodd.h" /> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{3C598F96-FB84-4d42-9B43-F697F53B0221}</ProjectGuid> diff --git a/projects/Win/vc12/unit-map-insdel.vcxproj b/projects/Win/vc12/unit-map-insdel.vcxproj index 9a504f1d..cc319af4 100644 --- a/projects/Win/vc12/unit-map-insdel.vcxproj +++ b/projects/Win/vc12/unit-map-insdel.vcxproj @@ -45,13 +45,14 @@ <ItemGroup> <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind.cpp" /> <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func.cpp" /> - <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func2.cpp" /> - <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func3.cpp" /> - <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func4.cpp" /> - <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func5.cpp" /> - <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func6.cpp" /> - <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func7.cpp" /> - <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func8.cpp" /> + <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_bronsonavltree.cpp" /> + <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_cuckoo.cpp" /> + <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_ellentree.cpp" /> + <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_michael.cpp" /> + <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_refinable.cpp" /> + <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_skip.cpp" /> + <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_split.cpp" /> + <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_striped.cpp" /> <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int.cpp" /> <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int.cpp" /> <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string.cpp" /> diff --git a/projects/source.unit.map.mk b/projects/source.unit.map.mk index f66e4a40..078ec837 100644 --- a/projects/source.unit.map.mk +++ b/projects/source.unit.map.mk @@ -3,17 +3,24 @@ CDSUNIT_MAP_SOURCES := \ tests/unit/map2/map_find_int.cpp \ tests/unit/map2/map_find_string.cpp \ tests/unit/map2/map_insdel_func.cpp \ - tests/unit/map2/map_insdel_func2.cpp \ - tests/unit/map2/map_insdel_func3.cpp \ - tests/unit/map2/map_insdel_func4.cpp \ - tests/unit/map2/map_insdel_func5.cpp \ - tests/unit/map2/map_insdel_func6.cpp \ - tests/unit/map2/map_insdel_func7.cpp \ - tests/unit/map2/map_insdel_func8.cpp \ + tests/unit/map2/map_insdel_func_michael.cpp \ + tests/unit/map2/map_insdel_func_split.cpp \ + tests/unit/map2/map_insdel_func_skip.cpp \ + tests/unit/map2/map_insdel_func_ellentree.cpp \ + tests/unit/map2/map_insdel_func_bronsonavltree.cpp \ + tests/unit/map2/map_insdel_func_striped.cpp \ + tests/unit/map2/map_insdel_func_refinable.cpp \ + tests/unit/map2/map_insdel_func_cuckoo.cpp \ tests/unit/map2/map_insdel_int.cpp \ tests/unit/map2/map_insdel_item_int.cpp \ tests/unit/map2/map_insdel_string.cpp \ tests/unit/map2/map_insdel_item_string.cpp \ tests/unit/map2/map_insfind_int.cpp \ tests/unit/map2/map_insdelfind.cpp \ - tests/unit/map2/map_delodd.cpp + tests/unit/map2/map_delodd.cpp \ + tests/unit/map2/map_delodd_michael.cpp \ + tests/unit/map2/map_delodd_bronsonavltree.cpp \ + tests/unit/map2/map_delodd_ellentree.cpp \ + tests/unit/map2/map_delodd_split.cpp \ + tests/unit/map2/map_delodd_skip.cpp \ + tests/unit/map2/map_delodd_cuckoo.cpp \ diff --git a/tests/unit/map2/map_delodd.cpp b/tests/unit/map2/map_delodd.cpp index a57c5d58..b2e974f4 100644 --- a/tests/unit/map2/map_delodd.cpp +++ b/tests/unit/map2/map_delodd.cpp @@ -1,744 +1,53 @@ //$$CDS-header$$ -#include "cppunit/thread.h" -#include "map2/map_types.h" -#include <algorithm> // random_shuffle +#include "map2/map_delodd.h" namespace map2 { + CPPUNIT_TEST_SUITE_REGISTRATION( Map_DelOdd ); -# define TEST_MAP(X) void X() { test<MapTypes<key_type, value_type>::X >(); } -# define TEST_MAP_EXTRACT(X) void X() { test_extract<MapTypes<key_type, value_type>::X >(); } -# define TEST_MAP_NOLF(X) void X() { test_nolf<MapTypes<key_type, value_type>::X >(); } -# define TEST_MAP_NOLF_EXTRACT(X) void X() { test_nolf_extract<MapTypes<key_type, value_type>::X >(); } - - namespace { - static size_t c_nMapSize = 1000000 ; // max map size - static size_t c_nInsThreadCount = 4 ; // insert thread count - static size_t c_nDelThreadCount = 4 ; // delete thread count - static size_t c_nExtractThreadCount = 4 ; // extract thread count - static size_t c_nMaxLoadFactor = 8 ; // maximum load factor - static bool c_bPrintGCState = true; - } - - namespace { - struct key_thread - { - size_t nKey; - size_t nThread; - - key_thread( size_t key, size_t threadNo ) - : nKey( key ) - , nThread( threadNo ) - {} - - key_thread() - {} - }; - - //typedef MapTypes<key_thread, size_t>::key_val key_value_pair; + size_t Map_DelOdd::c_nMapSize = 1000000 ; // max map size + size_t Map_DelOdd::c_nInsThreadCount = 4 ; // insert thread count + size_t Map_DelOdd::c_nDelThreadCount = 4 ; // delete thread count + size_t Map_DelOdd::c_nExtractThreadCount = 4 ; // extract thread count + size_t Map_DelOdd::c_nMaxLoadFactor = 8 ; // maximum load factor + bool Map_DelOdd::c_bPrintGCState = true; + + void Map_DelOdd::setUpParams( const CppUnitMini::TestCfg& cfg ) { + c_nMapSize = cfg.getULong("MapSize", static_cast<unsigned long>(c_nMapSize) ); + c_nInsThreadCount = cfg.getULong("InsThreadCount", static_cast<unsigned long>(c_nInsThreadCount) ); + c_nDelThreadCount = cfg.getULong("DelThreadCount", static_cast<unsigned long>(c_nDelThreadCount) ); + c_nExtractThreadCount = cfg.getULong("ExtractThreadCount", static_cast<unsigned long>(c_nExtractThreadCount) ); + c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", static_cast<unsigned long>(c_nMaxLoadFactor) ); + c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true ); + + if ( c_nInsThreadCount == 0 ) + c_nInsThreadCount = cds::OS::topology::processor_count(); + if ( c_nDelThreadCount == 0 && c_nExtractThreadCount == 0 ) { + c_nExtractThreadCount = cds::OS::topology::processor_count() / 2; + c_nDelThreadCount = cds::OS::topology::processor_count() - c_nExtractThreadCount; + } + + m_arrData.resize( c_nMapSize ); + for ( size_t i = 0; i < c_nMapSize; ++i ) + m_arrData[i] = i; + std::random_shuffle( m_arrData.begin(), m_arrData.end() ); } - template <> - struct cmp<key_thread> { - int operator ()(key_thread const& k1, key_thread const& k2) const - { - if ( k1.nKey < k2.nKey ) - return -1; - if ( k1.nKey > k2.nKey ) - return 1; - if ( k1.nThread < k2.nThread ) - return -1; - if ( k1.nThread > k2.nThread ) - return 1; - return 0; - } - int operator ()(key_thread const& k1, size_t k2) const - { - if ( k1.nKey < k2 ) - return -1; - if ( k1.nKey > k2 ) - return 1; - return 0; - } - int operator ()(size_t k1, key_thread const& k2) const - { - if ( k1 < k2.nKey ) - return -1; - if ( k1 > k2.nKey ) - return 1; - return 0; - } - }; - -} // namespace map2 - -namespace std { - template <> - struct less<map2::key_thread> - { - bool operator()(map2::key_thread const& k1, map2::key_thread const& k2) const - { - if ( k1.nKey <= k2.nKey ) - return k1.nKey < k2.nKey || k1.nThread < k2.nThread; - return false; - } - }; - - template <> - struct hash<map2::key_thread> - { - typedef size_t result_type; - typedef map2::key_thread argument_type; - - size_t operator()( map2::key_thread const& k ) const - { - return std::hash<size_t>()(k.nKey); - } - size_t operator()( size_t k ) const - { - return std::hash<size_t>()(k); - } - }; -} // namespace std - -namespace boost { - inline size_t hash_value( map2::key_thread const& k ) + void Map_DelOdd::myRun(const char *in_name, bool invert /*= false*/) { - return std::hash<size_t>()( k.nKey ); + setUpParams( m_Cfg.get( "Map_InsDel_func" )); + + run_MichaelMap(in_name, invert); + run_SplitList(in_name, invert); + run_SkipListMap(in_name, invert); + run_EllenBinTreeMap(in_name, invert); + run_BronsonAVLTreeMap(in_name, invert); + //run_StripedMap(in_name, invert); + //run_RefinableMap(in_name, invert); + run_CuckooMap(in_name, invert); + //run_StdMap(in_name, invert); + + endTestCase(); } - template <> - struct hash<map2::key_thread> - { - typedef size_t result_type; - typedef map2::key_thread argument_type; - - size_t operator()(map2::key_thread const& k) const - { - return boost::hash<size_t>()( k.nKey ); - } - size_t operator()(size_t k) const - { - return boost::hash<size_t>()( k ); - } - }; -} // namespace boost - -namespace map2 { - - class Map_DelOdd: public CppUnitMini::TestCase - { - std::vector<size_t> m_arrData; - - protected: - typedef key_thread key_type; - typedef size_t value_type; - typedef std::pair<key_type const, value_type> pair_type; - - atomics::atomic<size_t> m_nInsThreadCount; - - // Inserts keys from [0..N) - template <class Map> - class InsertThread: public CppUnitMini::TestThread - { - Map& m_Map; - - virtual InsertThread * clone() - { - return new InsertThread( *this ); - } - - struct ensure_func - { - template <typename Q> - void operator()( bool /*bNew*/, Q const& ) - {} - template <typename Q, typename V> - void operator()( bool /*bNew*/, Q const&, V& ) - {} - }; - public: - size_t m_nInsertSuccess; - size_t m_nInsertFailed; - - public: - InsertThread( CppUnitMini::ThreadPool& pool, Map& rMap ) - : CppUnitMini::TestThread( pool ) - , m_Map( rMap ) - {} - InsertThread( InsertThread& src ) - : CppUnitMini::TestThread( src ) - , m_Map( src.m_Map ) - {} - - Map_DelOdd& getTest() - { - return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test ); - } - - virtual void init() { cds::threading::Manager::attachThread() ; } - virtual void fini() { cds::threading::Manager::detachThread() ; } - - virtual void test() - { - Map& rMap = m_Map; - - m_nInsertSuccess = - m_nInsertFailed = 0; - - std::vector<size_t>& arrData = getTest().m_arrData; - for ( size_t i = 0; i < arrData.size(); ++i ) { - if ( rMap.insert( key_type( arrData[i], m_nThreadNo ))) - ++m_nInsertSuccess; - else - ++m_nInsertFailed; - } - - ensure_func f; - for ( size_t i = arrData.size() - 1; i > 0; --i ) { - if ( arrData[i] & 1 ) { - rMap.ensure( key_type( arrData[i], m_nThreadNo ), f ); - } - } - - getTest().m_nInsThreadCount.fetch_sub( 1, atomics::memory_order_acquire ); - } - }; - - struct key_equal { - bool operator()( key_type const& k1, key_type const& k2 ) const - { - return k1.nKey == k2.nKey; - } - bool operator()( size_t k1, key_type const& k2 ) const - { - return k1 == k2.nKey; - } - bool operator()( key_type const& k1, size_t k2 ) const - { - return k1.nKey == k2; - } - }; - - struct key_less { - bool operator()( key_type const& k1, key_type const& k2 ) const - { - return k1.nKey < k2.nKey; - } - bool operator()( size_t k1, key_type const& k2 ) const - { - return k1 < k2.nKey; - } - bool operator()( key_type const& k1, size_t k2 ) const - { - return k1.nKey < k2; - } - - typedef key_equal equal_to; - }; - - // Deletes odd keys from [0..N) - template <class Map> - class DeleteThread: public CppUnitMini::TestThread - { - Map& m_Map; - - virtual DeleteThread * clone() - { - return new DeleteThread( *this ); - } - public: - size_t m_nDeleteSuccess; - size_t m_nDeleteFailed; - - public: - DeleteThread( CppUnitMini::ThreadPool& pool, Map& rMap ) - : CppUnitMini::TestThread( pool ) - , m_Map( rMap ) - {} - DeleteThread( DeleteThread& src ) - : CppUnitMini::TestThread( src ) - , m_Map( src.m_Map ) - {} - - Map_DelOdd& getTest() - { - return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test ); - } - - virtual void init() { cds::threading::Manager::attachThread() ; } - virtual void fini() { cds::threading::Manager::detachThread() ; } - - virtual void test() - { - Map& rMap = m_Map; - - m_nDeleteSuccess = - m_nDeleteFailed = 0; - - std::vector<size_t>& arrData = getTest().m_arrData; - if ( m_nThreadNo & 1 ) { - for ( size_t k = 0; k < c_nInsThreadCount; ++k ) { - for ( size_t i = 0; i < arrData.size(); ++i ) { - if ( arrData[i] & 1 ) { - if ( rMap.erase_with( arrData[i], key_less() )) - ++m_nDeleteSuccess; - else - ++m_nDeleteFailed; - } - } - if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 ) - break; - } - } - else { - for ( size_t k = 0; k < c_nInsThreadCount; ++k ) { - for ( size_t i = arrData.size() - 1; i > 0; --i ) { - if ( arrData[i] & 1 ) { - if ( rMap.erase_with( arrData[i], key_less() )) - ++m_nDeleteSuccess; - else - ++m_nDeleteFailed; - } - } - if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 ) - break; - } - } - } - }; - - // Deletes odd keys from [0..N) - template <class GC, class Map > - class ExtractThread: public CppUnitMini::TestThread - { - Map& m_Map; - - virtual ExtractThread * clone() - { - return new ExtractThread( *this ); - } - public: - size_t m_nDeleteSuccess; - size_t m_nDeleteFailed; - - public: - ExtractThread( CppUnitMini::ThreadPool& pool, Map& rMap ) - : CppUnitMini::TestThread( pool ) - , m_Map( rMap ) - {} - ExtractThread( ExtractThread& src ) - : CppUnitMini::TestThread( src ) - , m_Map( src.m_Map ) - {} - - Map_DelOdd& getTest() - { - return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test ); - } - - virtual void init() { cds::threading::Manager::attachThread() ; } - virtual void fini() { cds::threading::Manager::detachThread() ; } - - virtual void test() - { - Map& rMap = m_Map; - - m_nDeleteSuccess = - m_nDeleteFailed = 0; - - typename Map::guarded_ptr gp; - - std::vector<size_t>& arrData = getTest().m_arrData; - if ( m_nThreadNo & 1 ) { - for ( size_t k = 0; k < c_nInsThreadCount; ++k ) { - for ( size_t i = 0; i < arrData.size(); ++i ) { - if ( arrData[i] & 1 ) { - gp = rMap.extract_with( arrData[i], key_less()); - if ( gp ) - ++m_nDeleteSuccess; - else - ++m_nDeleteFailed; - gp.release(); - } - } - if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 ) - break; - } - } - else { - for ( size_t k = 0; k < c_nInsThreadCount; ++k ) { - for ( size_t i = arrData.size() - 1; i > 0; --i ) { - if ( arrData[i] & 1 ) { - gp = rMap.extract_with( arrData[i], key_less()); - if ( gp ) - ++m_nDeleteSuccess; - else - ++m_nDeleteFailed; - gp.release(); - } - } - if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 ) - break; - } - } - } - }; - - template <class RCU, class Map > - class ExtractThread< cds::urcu::gc<RCU>, Map > : public CppUnitMini::TestThread - { - Map& m_Map; - - virtual ExtractThread * clone() - { - return new ExtractThread( *this ); - } - public: - size_t m_nDeleteSuccess; - size_t m_nDeleteFailed; - - public: - ExtractThread( CppUnitMini::ThreadPool& pool, Map& rMap ) - : CppUnitMini::TestThread( pool ) - , m_Map( rMap ) - {} - ExtractThread( ExtractThread& src ) - : CppUnitMini::TestThread( src ) - , m_Map( src.m_Map ) - {} - - Map_DelOdd& getTest() - { - return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test ); - } - - virtual void init() { cds::threading::Manager::attachThread() ; } - virtual void fini() { cds::threading::Manager::detachThread() ; } - - virtual void test() - { - Map& rMap = m_Map; - - m_nDeleteSuccess = - m_nDeleteFailed = 0; - - typename Map::exempt_ptr xp; - - std::vector<size_t>& arrData = getTest().m_arrData; - if ( m_nThreadNo & 1 ) { - for ( size_t k = 0; k < c_nInsThreadCount; ++k ) { - for ( size_t i = 0; i < arrData.size(); ++i ) { - if ( arrData[i] & 1 ) { - if ( Map::c_bExtractLockExternal ) { - { - typename Map::rcu_lock l; - xp = rMap.extract_with( arrData[i], key_less() ); - if ( xp ) - ++m_nDeleteSuccess; - else - ++m_nDeleteFailed; - } - } - else { - xp = rMap.extract_with( arrData[i], key_less() ); - if ( xp ) - ++m_nDeleteSuccess; - else - ++m_nDeleteFailed; - } - xp.release(); - } - } - if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 ) - break; - } - } - else { - for ( size_t k = 0; k < c_nInsThreadCount; ++k ) { - for ( size_t i = arrData.size() - 1; i > 0; --i ) { - if ( arrData[i] & 1 ) { - if ( Map::c_bExtractLockExternal ) { - { - typename Map::rcu_lock l; - xp = rMap.extract_with( arrData[i], key_less() ); - if ( xp ) - ++m_nDeleteSuccess; - else - ++m_nDeleteFailed; - } - } - else { - xp = rMap.extract_with( arrData[i], key_less() ); - if ( xp ) - ++m_nDeleteSuccess; - else - ++m_nDeleteFailed; - } - xp.release(); - } - } - if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 ) - break; - } - } - } - }; - - protected: - template <class Map> - void do_test( size_t nLoadFactor ) - { - Map testMap( c_nMapSize, nLoadFactor ); - do_test_with( testMap ); - } - - template <class Map> - void do_test_extract( size_t nLoadFactor ) - { - Map testMap( c_nMapSize, nLoadFactor ); - do_test_extract_with( testMap ); - } - - template <class Map> - void do_test_with( Map& testMap ) - { - typedef InsertThread<Map> insert_thread; - typedef DeleteThread<Map> delete_thread; - - m_nInsThreadCount.store( c_nInsThreadCount, atomics::memory_order_release ); - - CppUnitMini::ThreadPool pool( *this ); - pool.add( new insert_thread( pool, testMap ), c_nInsThreadCount ); - pool.add( new delete_thread( pool, testMap ), c_nDelThreadCount ? c_nDelThreadCount : cds::OS::topology::processor_count()); - pool.run(); - CPPUNIT_MSG( " Duration=" << pool.avgDuration() ); - - size_t nInsertSuccess = 0; - size_t nInsertFailed = 0; - size_t nDeleteSuccess = 0; - size_t nDeleteFailed = 0; - for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) { - insert_thread * pThread = dynamic_cast<insert_thread *>( *it ); - if ( pThread ) { - nInsertSuccess += pThread->m_nInsertSuccess; - nInsertFailed += pThread->m_nInsertFailed; - } - else { - delete_thread * p = static_cast<delete_thread *>( *it ); - nDeleteSuccess += p->m_nDeleteSuccess; - nDeleteFailed += p->m_nDeleteFailed; - } - } - - CPPUNIT_MSG( " Totals (success/failed): \n\t" - << " Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t" - << " Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t" - ); - CPPUNIT_CHECK( nInsertSuccess == c_nMapSize * c_nInsThreadCount ); - CPPUNIT_CHECK( nInsertFailed == 0 ); - - analyze( testMap ); - } - - template <class Map> - void do_test_extract_with( Map& testMap ) - { - typedef InsertThread<Map> insert_thread; - typedef DeleteThread<Map> delete_thread; - typedef ExtractThread< typename Map::gc, Map > extract_thread; - - m_nInsThreadCount.store( c_nInsThreadCount, atomics::memory_order_release ); - - CppUnitMini::ThreadPool pool( *this ); - pool.add( new insert_thread( pool, testMap ), c_nInsThreadCount ); - if ( c_nDelThreadCount ) - pool.add( new delete_thread( pool, testMap ), c_nDelThreadCount ); - if ( c_nExtractThreadCount ) - pool.add( new extract_thread( pool, testMap ), c_nExtractThreadCount ); - pool.run(); - CPPUNIT_MSG( " Duration=" << pool.avgDuration() ); - - size_t nInsertSuccess = 0; - size_t nInsertFailed = 0; - size_t nDeleteSuccess = 0; - size_t nDeleteFailed = 0; - size_t nExtractSuccess = 0; - size_t nExtractFailed = 0; - for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) { - insert_thread * pThread = dynamic_cast<insert_thread *>( *it ); - if ( pThread ) { - nInsertSuccess += pThread->m_nInsertSuccess; - nInsertFailed += pThread->m_nInsertFailed; - } - else { - delete_thread * p = dynamic_cast<delete_thread *>( *it ); - if ( p ) { - nDeleteSuccess += p->m_nDeleteSuccess; - nDeleteFailed += p->m_nDeleteFailed; - } - else { - extract_thread * pExtract = dynamic_cast<extract_thread *>( *it ); - assert( pExtract ); - nExtractSuccess += pExtract->m_nDeleteSuccess; - nExtractFailed += pExtract->m_nDeleteFailed; - } - } - } - - CPPUNIT_MSG( " Totals (success/failed): \n\t" - << " Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t" - << " Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t" - << " Extract=" << nExtractSuccess << '/' << nExtractFailed << "\n\t" - ); - CPPUNIT_CHECK( nInsertSuccess == c_nMapSize * c_nInsThreadCount ); - CPPUNIT_CHECK( nInsertFailed == 0 ); - - analyze( testMap ); - } - - template <class Map> - void analyze( Map& testMap ) - { - cds::OS::Timer timer; - - // All even keys must be in the map - { - size_t nErrorCount = 0; - CPPUNIT_MSG( " Check even keys..." ); - for ( size_t n = 0; n < c_nMapSize; n +=2 ) { - for ( size_t i = 0; i < c_nInsThreadCount; ++i ) { - if ( !testMap.find( key_type(n, i) ) ) { - if ( ++nErrorCount < 10 ) { - CPPUNIT_MSG( "key " << n << "-" << i << " is not found!"); - } - } - } - } - CPPUNIT_CHECK_EX( nErrorCount == 0, "Totals: " << nErrorCount << " keys is not found"); - } - - check_before_cleanup( testMap ); - - CPPUNIT_MSG( " Clear map (single-threaded)..." ); - timer.reset(); - testMap.clear(); - CPPUNIT_MSG( " Duration=" << timer.duration() ); - CPPUNIT_CHECK_EX( testMap.empty(), ((long long) testMap.size()) ); - - additional_check( testMap ); - print_stat( testMap ); - - additional_cleanup( testMap ); - } - - - template <class Map> - void test() - { - CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount - << " delete thread count=" << c_nDelThreadCount - << " set size=" << c_nMapSize - ); - - for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) { - CPPUNIT_MSG( "Load factor=" << nLoadFactor ); - do_test<Map>( nLoadFactor ); - if ( c_bPrintGCState ) - print_gc_state(); - } - } - - template <class Map> - void test_extract() - { - CPPUNIT_MSG( "Thread count: insert=" << c_nInsThreadCount - << ", delete=" << c_nDelThreadCount - << ", extract=" << c_nExtractThreadCount - << "; set size=" << c_nMapSize - ); - - for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) { - CPPUNIT_MSG( "Load factor=" << nLoadFactor ); - do_test_extract<Map>( nLoadFactor ); - if ( c_bPrintGCState ) - print_gc_state(); - } - } - - template <class Map> - void test_nolf() - { - CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount - << " delete thread count=" << c_nDelThreadCount - << " set size=" << c_nMapSize - ); - - Map s; - do_test_with( s ); - if ( c_bPrintGCState ) - print_gc_state(); - } - - template <class Map> - void test_nolf_extract() - { - CPPUNIT_MSG( "Thread count: insert=" << c_nInsThreadCount - << ", delete=" << c_nDelThreadCount - << ", extract=" << c_nExtractThreadCount - << "; set size=" << c_nMapSize - ); - - Map s; - do_test_extract_with( s ); - if ( c_bPrintGCState ) - print_gc_state(); - } - - void setUpParams( const CppUnitMini::TestCfg& cfg ) { - c_nMapSize = cfg.getULong("MapSize", static_cast<unsigned long>(c_nMapSize) ); - c_nInsThreadCount = cfg.getULong("InsThreadCount", static_cast<unsigned long>(c_nInsThreadCount) ); - c_nDelThreadCount = cfg.getULong("DelThreadCount", static_cast<unsigned long>(c_nDelThreadCount) ); - c_nExtractThreadCount = cfg.getULong("ExtractThreadCount", static_cast<unsigned long>(c_nExtractThreadCount) ); - c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", static_cast<unsigned long>(c_nMaxLoadFactor) ); - c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true ); - - if ( c_nInsThreadCount == 0 ) - c_nInsThreadCount = cds::OS::topology::processor_count(); - if ( c_nDelThreadCount == 0 && c_nExtractThreadCount == 0 ) { - c_nExtractThreadCount = cds::OS::topology::processor_count() / 2; - c_nDelThreadCount = cds::OS::topology::processor_count() - c_nExtractThreadCount; - } - - m_arrData.resize( c_nMapSize ); - for ( size_t i = 0; i < c_nMapSize; ++i ) - m_arrData[i] = i; - std::random_shuffle( m_arrData.begin(), m_arrData.end() ); - } - -# include "map2/map_defs.h" - CDSUNIT_DECLARE_MichaelMap - CDSUNIT_DECLARE_SplitList - //CDSUNIT_DECLARE_StripedMap - //CDSUNIT_DECLARE_RefinableMap - CDSUNIT_DECLARE_CuckooMap - CDSUNIT_DECLARE_SkipListMap - CDSUNIT_DECLARE_EllenBinTreeMap - CDSUNIT_DECLARE_BronsonAVLTreeMap - //CDSUNIT_DECLARE_StdMap - - CPPUNIT_TEST_SUITE( Map_DelOdd ) - CDSUNIT_TEST_MichaelMap - CDSUNIT_TEST_SplitList - CDSUNIT_TEST_SkipListMap - CDSUNIT_TEST_EllenBinTreeMap - CDSUNIT_TEST_BronsonAVLTreeMap - //CDSUNIT_TEST_StripedMap - //CDSUNIT_TEST_RefinableMap - CDSUNIT_TEST_CuckooMap - //CDSUNIT_TEST_StdMap - CPPUNIT_TEST_SUITE_END() - }; - - CPPUNIT_TEST_SUITE_REGISTRATION( Map_DelOdd ); } // namespace map2 diff --git a/tests/unit/map2/map_delodd.h b/tests/unit/map2/map_delodd.h new file mode 100644 index 00000000..226098bd --- /dev/null +++ b/tests/unit/map2/map_delodd.h @@ -0,0 +1,723 @@ +//$$CDS-header$$ + +#include "cppunit/thread.h" +#include "map2/map_types.h" +#include <algorithm> // random_shuffle + +namespace map2 { + +# define TEST_MAP(X) void X() { test<MapTypes<key_type, value_type>::X >(); } +# define TEST_MAP_EXTRACT(X) void X() { test_extract<MapTypes<key_type, value_type>::X >(); } +# define TEST_MAP_NOLF(X) void X() { test_nolf<MapTypes<key_type, value_type>::X >(); } +# define TEST_MAP_NOLF_EXTRACT(X) void X() { test_nolf_extract<MapTypes<key_type, value_type>::X >(); } + + namespace { + struct key_thread + { + size_t nKey; + size_t nThread; + + key_thread( size_t key, size_t threadNo ) + : nKey( key ) + , nThread( threadNo ) + {} + + key_thread() + {} + }; + + //typedef MapTypes<key_thread, size_t>::key_val key_value_pair; + } + + template <> + struct cmp<key_thread> { + int operator ()(key_thread const& k1, key_thread const& k2) const + { + if ( k1.nKey < k2.nKey ) + return -1; + if ( k1.nKey > k2.nKey ) + return 1; + if ( k1.nThread < k2.nThread ) + return -1; + if ( k1.nThread > k2.nThread ) + return 1; + return 0; + } + int operator ()(key_thread const& k1, size_t k2) const + { + if ( k1.nKey < k2 ) + return -1; + if ( k1.nKey > k2 ) + return 1; + return 0; + } + int operator ()(size_t k1, key_thread const& k2) const + { + if ( k1 < k2.nKey ) + return -1; + if ( k1 > k2.nKey ) + return 1; + return 0; + } + }; + +} // namespace map2 + +namespace std { + template <> + struct less<map2::key_thread> + { + bool operator()(map2::key_thread const& k1, map2::key_thread const& k2) const + { + if ( k1.nKey <= k2.nKey ) + return k1.nKey < k2.nKey || k1.nThread < k2.nThread; + return false; + } + }; + + template <> + struct hash<map2::key_thread> + { + typedef size_t result_type; + typedef map2::key_thread argument_type; + + size_t operator()( map2::key_thread const& k ) const + { + return std::hash<size_t>()(k.nKey); + } + size_t operator()( size_t k ) const + { + return std::hash<size_t>()(k); + } + }; +} // namespace std + +namespace boost { + inline size_t hash_value( map2::key_thread const& k ) + { + return std::hash<size_t>()( k.nKey ); + } + + template <> + struct hash<map2::key_thread> + { + typedef size_t result_type; + typedef map2::key_thread argument_type; + + size_t operator()(map2::key_thread const& k) const + { + return boost::hash<size_t>()( k.nKey ); + } + size_t operator()(size_t k) const + { + return boost::hash<size_t>()( k ); + } + }; +} // namespace boost + +namespace map2 { + + class Map_DelOdd: public CppUnitMini::TestCase + { + static size_t c_nMapSize; // max map size + static size_t c_nInsThreadCount; // insert thread count + static size_t c_nDelThreadCount; // delete thread count + static size_t c_nExtractThreadCount; // extract thread count + static size_t c_nMaxLoadFactor; // maximum load factor + static bool c_bPrintGCState; + + std::vector<size_t> m_arrData; + + protected: + typedef CppUnitMini::TestCase Base; + + typedef key_thread key_type; + typedef size_t value_type; + typedef std::pair<key_type const, value_type> pair_type; + + atomics::atomic<size_t> m_nInsThreadCount; + + // Inserts keys from [0..N) + template <class Map> + class InsertThread: public CppUnitMini::TestThread + { + Map& m_Map; + + virtual InsertThread * clone() + { + return new InsertThread( *this ); + } + + struct ensure_func + { + template <typename Q> + void operator()( bool /*bNew*/, Q const& ) + {} + template <typename Q, typename V> + void operator()( bool /*bNew*/, Q const&, V& ) + {} + }; + public: + size_t m_nInsertSuccess; + size_t m_nInsertFailed; + + public: + InsertThread( CppUnitMini::ThreadPool& pool, Map& rMap ) + : CppUnitMini::TestThread( pool ) + , m_Map( rMap ) + {} + InsertThread( InsertThread& src ) + : CppUnitMini::TestThread( src ) + , m_Map( src.m_Map ) + {} + + Map_DelOdd& getTest() + { + return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test ); + } + + virtual void init() { cds::threading::Manager::attachThread() ; } + virtual void fini() { cds::threading::Manager::detachThread() ; } + + virtual void test() + { + Map& rMap = m_Map; + + m_nInsertSuccess = + m_nInsertFailed = 0; + + std::vector<size_t>& arrData = getTest().m_arrData; + for ( size_t i = 0; i < arrData.size(); ++i ) { + if ( rMap.insert( key_type( arrData[i], m_nThreadNo ))) + ++m_nInsertSuccess; + else + ++m_nInsertFailed; + } + + ensure_func f; + for ( size_t i = arrData.size() - 1; i > 0; --i ) { + if ( arrData[i] & 1 ) { + rMap.ensure( key_type( arrData[i], m_nThreadNo ), f ); + } + } + + getTest().m_nInsThreadCount.fetch_sub( 1, atomics::memory_order_acquire ); + } + }; + + struct key_equal { + bool operator()( key_type const& k1, key_type const& k2 ) const + { + return k1.nKey == k2.nKey; + } + bool operator()( size_t k1, key_type const& k2 ) const + { + return k1 == k2.nKey; + } + bool operator()( key_type const& k1, size_t k2 ) const + { + return k1.nKey == k2; + } + }; + + struct key_less { + bool operator()( key_type const& k1, key_type const& k2 ) const + { + return k1.nKey < k2.nKey; + } + bool operator()( size_t k1, key_type const& k2 ) const + { + return k1 < k2.nKey; + } + bool operator()( key_type const& k1, size_t k2 ) const + { + return k1.nKey < k2; + } + + typedef key_equal equal_to; + }; + + // Deletes odd keys from [0..N) + template <class Map> + class DeleteThread: public CppUnitMini::TestThread + { + Map& m_Map; + + virtual DeleteThread * clone() + { + return new DeleteThread( *this ); + } + public: + size_t m_nDeleteSuccess; + size_t m_nDeleteFailed; + + public: + DeleteThread( CppUnitMini::ThreadPool& pool, Map& rMap ) + : CppUnitMini::TestThread( pool ) + , m_Map( rMap ) + {} + DeleteThread( DeleteThread& src ) + : CppUnitMini::TestThread( src ) + , m_Map( src.m_Map ) + {} + + Map_DelOdd& getTest() + { + return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test ); + } + + virtual void init() { cds::threading::Manager::attachThread() ; } + virtual void fini() { cds::threading::Manager::detachThread() ; } + + virtual void test() + { + Map& rMap = m_Map; + + m_nDeleteSuccess = + m_nDeleteFailed = 0; + + std::vector<size_t>& arrData = getTest().m_arrData; + if ( m_nThreadNo & 1 ) { + for ( size_t k = 0; k < c_nInsThreadCount; ++k ) { + for ( size_t i = 0; i < arrData.size(); ++i ) { + if ( arrData[i] & 1 ) { + if ( rMap.erase_with( arrData[i], key_less() )) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + } + if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 ) + break; + } + } + else { + for ( size_t k = 0; k < c_nInsThreadCount; ++k ) { + for ( size_t i = arrData.size() - 1; i > 0; --i ) { + if ( arrData[i] & 1 ) { + if ( rMap.erase_with( arrData[i], key_less() )) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + } + if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 ) + break; + } + } + } + }; + + // Deletes odd keys from [0..N) + template <class GC, class Map > + class ExtractThread: public CppUnitMini::TestThread + { + Map& m_Map; + + virtual ExtractThread * clone() + { + return new ExtractThread( *this ); + } + public: + size_t m_nDeleteSuccess; + size_t m_nDeleteFailed; + + public: + ExtractThread( CppUnitMini::ThreadPool& pool, Map& rMap ) + : CppUnitMini::TestThread( pool ) + , m_Map( rMap ) + {} + ExtractThread( ExtractThread& src ) + : CppUnitMini::TestThread( src ) + , m_Map( src.m_Map ) + {} + + Map_DelOdd& getTest() + { + return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test ); + } + + virtual void init() { cds::threading::Manager::attachThread() ; } + virtual void fini() { cds::threading::Manager::detachThread() ; } + + virtual void test() + { + Map& rMap = m_Map; + + m_nDeleteSuccess = + m_nDeleteFailed = 0; + + typename Map::guarded_ptr gp; + + std::vector<size_t>& arrData = getTest().m_arrData; + if ( m_nThreadNo & 1 ) { + for ( size_t k = 0; k < c_nInsThreadCount; ++k ) { + for ( size_t i = 0; i < arrData.size(); ++i ) { + if ( arrData[i] & 1 ) { + gp = rMap.extract_with( arrData[i], key_less()); + if ( gp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + gp.release(); + } + } + if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 ) + break; + } + } + else { + for ( size_t k = 0; k < c_nInsThreadCount; ++k ) { + for ( size_t i = arrData.size() - 1; i > 0; --i ) { + if ( arrData[i] & 1 ) { + gp = rMap.extract_with( arrData[i], key_less()); + if ( gp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + gp.release(); + } + } + if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 ) + break; + } + } + } + }; + + template <class RCU, class Map > + class ExtractThread< cds::urcu::gc<RCU>, Map > : public CppUnitMini::TestThread + { + Map& m_Map; + + virtual ExtractThread * clone() + { + return new ExtractThread( *this ); + } + public: + size_t m_nDeleteSuccess; + size_t m_nDeleteFailed; + + public: + ExtractThread( CppUnitMini::ThreadPool& pool, Map& rMap ) + : CppUnitMini::TestThread( pool ) + , m_Map( rMap ) + {} + ExtractThread( ExtractThread& src ) + : CppUnitMini::TestThread( src ) + , m_Map( src.m_Map ) + {} + + Map_DelOdd& getTest() + { + return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test ); + } + + virtual void init() { cds::threading::Manager::attachThread() ; } + virtual void fini() { cds::threading::Manager::detachThread() ; } + + virtual void test() + { + Map& rMap = m_Map; + + m_nDeleteSuccess = + m_nDeleteFailed = 0; + + typename Map::exempt_ptr xp; + + std::vector<size_t>& arrData = getTest().m_arrData; + if ( m_nThreadNo & 1 ) { + for ( size_t k = 0; k < c_nInsThreadCount; ++k ) { + for ( size_t i = 0; i < arrData.size(); ++i ) { + if ( arrData[i] & 1 ) { + if ( Map::c_bExtractLockExternal ) { + { + typename Map::rcu_lock l; + xp = rMap.extract_with( arrData[i], key_less() ); + if ( xp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + } + else { + xp = rMap.extract_with( arrData[i], key_less() ); + if ( xp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + xp.release(); + } + } + if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 ) + break; + } + } + else { + for ( size_t k = 0; k < c_nInsThreadCount; ++k ) { + for ( size_t i = arrData.size() - 1; i > 0; --i ) { + if ( arrData[i] & 1 ) { + if ( Map::c_bExtractLockExternal ) { + { + typename Map::rcu_lock l; + xp = rMap.extract_with( arrData[i], key_less() ); + if ( xp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + } + else { + xp = rMap.extract_with( arrData[i], key_less() ); + if ( xp ) + ++m_nDeleteSuccess; + else + ++m_nDeleteFailed; + } + xp.release(); + } + } + if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 ) + break; + } + } + } + }; + + protected: + template <class Map> + void do_test( size_t nLoadFactor ) + { + Map testMap( c_nMapSize, nLoadFactor ); + do_test_with( testMap ); + } + + template <class Map> + void do_test_extract( size_t nLoadFactor ) + { + Map testMap( c_nMapSize, nLoadFactor ); + do_test_extract_with( testMap ); + } + + template <class Map> + void do_test_with( Map& testMap ) + { + typedef InsertThread<Map> insert_thread; + typedef DeleteThread<Map> delete_thread; + + m_nInsThreadCount.store( c_nInsThreadCount, atomics::memory_order_release ); + + CppUnitMini::ThreadPool pool( *this ); + pool.add( new insert_thread( pool, testMap ), c_nInsThreadCount ); + pool.add( new delete_thread( pool, testMap ), c_nDelThreadCount ? c_nDelThreadCount : cds::OS::topology::processor_count()); + pool.run(); + CPPUNIT_MSG( " Duration=" << pool.avgDuration() ); + + size_t nInsertSuccess = 0; + size_t nInsertFailed = 0; + size_t nDeleteSuccess = 0; + size_t nDeleteFailed = 0; + for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) { + insert_thread * pThread = dynamic_cast<insert_thread *>( *it ); + if ( pThread ) { + nInsertSuccess += pThread->m_nInsertSuccess; + nInsertFailed += pThread->m_nInsertFailed; + } + else { + delete_thread * p = static_cast<delete_thread *>( *it ); + nDeleteSuccess += p->m_nDeleteSuccess; + nDeleteFailed += p->m_nDeleteFailed; + } + } + + CPPUNIT_MSG( " Totals (success/failed): \n\t" + << " Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t" + << " Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t" + ); + CPPUNIT_CHECK( nInsertSuccess == c_nMapSize * c_nInsThreadCount ); + CPPUNIT_CHECK( nInsertFailed == 0 ); + + analyze( testMap ); + } + + template <class Map> + void do_test_extract_with( Map& testMap ) + { + typedef InsertThread<Map> insert_thread; + typedef DeleteThread<Map> delete_thread; + typedef ExtractThread< typename Map::gc, Map > extract_thread; + + m_nInsThreadCount.store( c_nInsThreadCount, atomics::memory_order_release ); + + CppUnitMini::ThreadPool pool( *this ); + pool.add( new insert_thread( pool, testMap ), c_nInsThreadCount ); + if ( c_nDelThreadCount ) + pool.add( new delete_thread( pool, testMap ), c_nDelThreadCount ); + if ( c_nExtractThreadCount ) + pool.add( new extract_thread( pool, testMap ), c_nExtractThreadCount ); + pool.run(); + CPPUNIT_MSG( " Duration=" << pool.avgDuration() ); + + size_t nInsertSuccess = 0; + size_t nInsertFailed = 0; + size_t nDeleteSuccess = 0; + size_t nDeleteFailed = 0; + size_t nExtractSuccess = 0; + size_t nExtractFailed = 0; + for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) { + insert_thread * pThread = dynamic_cast<insert_thread *>( *it ); + if ( pThread ) { + nInsertSuccess += pThread->m_nInsertSuccess; + nInsertFailed += pThread->m_nInsertFailed; + } + else { + delete_thread * p = dynamic_cast<delete_thread *>( *it ); + if ( p ) { + nDeleteSuccess += p->m_nDeleteSuccess; + nDeleteFailed += p->m_nDeleteFailed; + } + else { + extract_thread * pExtract = dynamic_cast<extract_thread *>( *it ); + assert( pExtract ); + nExtractSuccess += pExtract->m_nDeleteSuccess; + nExtractFailed += pExtract->m_nDeleteFailed; + } + } + } + + CPPUNIT_MSG( " Totals (success/failed): \n\t" + << " Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t" + << " Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t" + << " Extract=" << nExtractSuccess << '/' << nExtractFailed << "\n\t" + ); + CPPUNIT_CHECK( nInsertSuccess == c_nMapSize * c_nInsThreadCount ); + CPPUNIT_CHECK( nInsertFailed == 0 ); + + analyze( testMap ); + } + + template <class Map> + void analyze( Map& testMap ) + { + cds::OS::Timer timer; + + // All even keys must be in the map + { + size_t nErrorCount = 0; + CPPUNIT_MSG( " Check even keys..." ); + for ( size_t n = 0; n < c_nMapSize; n +=2 ) { + for ( size_t i = 0; i < c_nInsThreadCount; ++i ) { + if ( !testMap.find( key_type(n, i) ) ) { + if ( ++nErrorCount < 10 ) { + CPPUNIT_MSG( "key " << n << "-" << i << " is not found!"); + } + } + } + } + CPPUNIT_CHECK_EX( nErrorCount == 0, "Totals: " << nErrorCount << " keys is not found"); + } + + check_before_cleanup( testMap ); + + CPPUNIT_MSG( " Clear map (single-threaded)..." ); + timer.reset(); + testMap.clear(); + CPPUNIT_MSG( " Duration=" << timer.duration() ); + CPPUNIT_CHECK_EX( testMap.empty(), ((long long) testMap.size()) ); + + additional_check( testMap ); + print_stat( testMap ); + + additional_cleanup( testMap ); + } + + + template <class Map> + void test() + { + CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount + << " delete thread count=" << c_nDelThreadCount + << " set size=" << c_nMapSize + ); + + for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) { + CPPUNIT_MSG( "Load factor=" << nLoadFactor ); + do_test<Map>( nLoadFactor ); + if ( c_bPrintGCState ) + print_gc_state(); + } + } + + template <class Map> + void test_extract() + { + CPPUNIT_MSG( "Thread count: insert=" << c_nInsThreadCount + << ", delete=" << c_nDelThreadCount + << ", extract=" << c_nExtractThreadCount + << "; set size=" << c_nMapSize + ); + + for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) { + CPPUNIT_MSG( "Load factor=" << nLoadFactor ); + do_test_extract<Map>( nLoadFactor ); + if ( c_bPrintGCState ) + print_gc_state(); + } + } + + template <class Map> + void test_nolf() + { + CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount + << " delete thread count=" << c_nDelThreadCount + << " set size=" << c_nMapSize + ); + + Map s; + do_test_with( s ); + if ( c_bPrintGCState ) + print_gc_state(); + } + + template <class Map> + void test_nolf_extract() + { + CPPUNIT_MSG( "Thread count: insert=" << c_nInsThreadCount + << ", delete=" << c_nDelThreadCount + << ", extract=" << c_nExtractThreadCount + << "; set size=" << c_nMapSize + ); + + Map s; + do_test_extract_with( s ); + if ( c_bPrintGCState ) + print_gc_state(); + } + + void setUpParams( const CppUnitMini::TestCfg& cfg ); + + void run_MichaelMap(const char *in_name, bool invert = false); + void run_SplitList(const char *in_name, bool invert = false); + //void run_StripedMap(const char *in_name, bool invert = false); + //void run_RefinableMap(const char *in_name, bool invert = false); + void run_CuckooMap(const char *in_name, bool invert = false); + void run_SkipListMap(const char *in_name, bool invert = false); + void run_EllenBinTreeMap(const char *in_name, bool invert = false); + void run_BronsonAVLTreeMap(const char *in_name, bool invert = false); + //void run_StdMap(const char *in_name, bool invert = false); + + virtual void myRun(const char *in_name, bool invert = false); + +# include "map2/map_defs.h" + CDSUNIT_DECLARE_MichaelMap + CDSUNIT_DECLARE_SplitList + //CDSUNIT_DECLARE_StripedMap + //CDSUNIT_DECLARE_RefinableMap + CDSUNIT_DECLARE_CuckooMap + CDSUNIT_DECLARE_SkipListMap + CDSUNIT_DECLARE_EllenBinTreeMap + CDSUNIT_DECLARE_BronsonAVLTreeMap + //CDSUNIT_DECLARE_StdMap + }; +} // namespace map2 diff --git a/tests/unit/map2/map_delodd_bronsonavltree.cpp b/tests/unit/map2/map_delodd_bronsonavltree.cpp new file mode 100644 index 00000000..0448891b --- /dev/null +++ b/tests/unit/map2/map_delodd_bronsonavltree.cpp @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#include "map2/map_delodd.h" + +namespace map2 { + CPPUNIT_TEST_SUITE_PART( Map_DelOdd, run_BronsonAVLTreeMap ) + CDSUNIT_TEST_BronsonAVLTreeMap + CPPUNIT_TEST_SUITE_END_PART() +} // namespace map2 diff --git a/tests/unit/map2/map_delodd_cuckoo.cpp b/tests/unit/map2/map_delodd_cuckoo.cpp new file mode 100644 index 00000000..191d35a9 --- /dev/null +++ b/tests/unit/map2/map_delodd_cuckoo.cpp @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#include "map2/map_delodd.h" + +namespace map2 { + CPPUNIT_TEST_SUITE_PART( Map_DelOdd, run_CuckooMap ) + CDSUNIT_TEST_CuckooMap + CPPUNIT_TEST_SUITE_END_PART() +} // namespace map2 diff --git a/tests/unit/map2/map_delodd_ellentree.cpp b/tests/unit/map2/map_delodd_ellentree.cpp new file mode 100644 index 00000000..e6883aa4 --- /dev/null +++ b/tests/unit/map2/map_delodd_ellentree.cpp @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#include "map2/map_delodd.h" + +namespace map2 { + CPPUNIT_TEST_SUITE_PART( Map_DelOdd, run_EllenBinTreeMap ) + CDSUNIT_TEST_EllenBinTreeMap + CPPUNIT_TEST_SUITE_END_PART() +} // namespace map2 diff --git a/tests/unit/map2/map_delodd_michael.cpp b/tests/unit/map2/map_delodd_michael.cpp new file mode 100644 index 00000000..c114aed0 --- /dev/null +++ b/tests/unit/map2/map_delodd_michael.cpp @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#include "map2/map_delodd.h" + +namespace map2 { + CPPUNIT_TEST_SUITE_PART( Map_DelOdd, run_MichaelMap ) + CDSUNIT_TEST_MichaelMap + CPPUNIT_TEST_SUITE_END_PART() +} // namespace map2 diff --git a/tests/unit/map2/map_delodd_skip.cpp b/tests/unit/map2/map_delodd_skip.cpp new file mode 100644 index 00000000..bb92b6d7 --- /dev/null +++ b/tests/unit/map2/map_delodd_skip.cpp @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#include "map2/map_delodd.h" + +namespace map2 { + CPPUNIT_TEST_SUITE_PART( Map_DelOdd, run_SkipListMap ) + CDSUNIT_TEST_SkipListMap + CPPUNIT_TEST_SUITE_END_PART() +} // namespace map2 diff --git a/tests/unit/map2/map_delodd_split.cpp b/tests/unit/map2/map_delodd_split.cpp new file mode 100644 index 00000000..b8895cb7 --- /dev/null +++ b/tests/unit/map2/map_delodd_split.cpp @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#include "map2/map_delodd.h" + +namespace map2 { + CPPUNIT_TEST_SUITE_PART( Map_DelOdd, run_SplitList ) + CDSUNIT_TEST_SplitList + CPPUNIT_TEST_SUITE_END_PART() +} // namespace map2 diff --git a/tests/unit/map2/map_insdel_func.cpp b/tests/unit/map2/map_insdel_func.cpp index 6232125a..6898d390 100644 --- a/tests/unit/map2/map_insdel_func.cpp +++ b/tests/unit/map2/map_insdel_func.cpp @@ -46,8 +46,4 @@ namespace map2 { endTestCase(); } - - CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_MichaelMap ) - CDSUNIT_TEST_MichaelMap - CPPUNIT_TEST_SUITE_END_PART() } // namespace map2 diff --git a/tests/unit/map2/map_insdel_func2.cpp b/tests/unit/map2/map_insdel_func2.cpp deleted file mode 100644 index da1c3fac..00000000 --- a/tests/unit/map2/map_insdel_func2.cpp +++ /dev/null @@ -1,10 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_insdel_func.h" - -namespace map2 { - CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_SplitList ) - CDSUNIT_TEST_SplitList - CPPUNIT_TEST_SUITE_END_PART() -} // namespace map2 - diff --git a/tests/unit/map2/map_insdel_func3.cpp b/tests/unit/map2/map_insdel_func3.cpp deleted file mode 100644 index 9cec610e..00000000 --- a/tests/unit/map2/map_insdel_func3.cpp +++ /dev/null @@ -1,10 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_insdel_func.h" - -namespace map2 { - CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_SkipListMap ) - CDSUNIT_TEST_SkipListMap - CPPUNIT_TEST_SUITE_END_PART() -} // namespace map2 - diff --git a/tests/unit/map2/map_insdel_func4.cpp b/tests/unit/map2/map_insdel_func4.cpp deleted file mode 100644 index 1533d352..00000000 --- a/tests/unit/map2/map_insdel_func4.cpp +++ /dev/null @@ -1,10 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_insdel_func.h" - -namespace map2 { - CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_EllenBinTreeMap ) - CDSUNIT_TEST_EllenBinTreeMap - CPPUNIT_TEST_SUITE_END_PART() -} // namespace map2 - diff --git a/tests/unit/map2/map_insdel_func5.cpp b/tests/unit/map2/map_insdel_func5.cpp deleted file mode 100644 index 30d277d3..00000000 --- a/tests/unit/map2/map_insdel_func5.cpp +++ /dev/null @@ -1,9 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_insdel_func.h" - -namespace map2 { - CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_BronsonAVLTreeMap ) - CDSUNIT_TEST_BronsonAVLTreeMap - CPPUNIT_TEST_SUITE_END_PART() -} // namespace map2 diff --git a/tests/unit/map2/map_insdel_func6.cpp b/tests/unit/map2/map_insdel_func6.cpp deleted file mode 100644 index f6841183..00000000 --- a/tests/unit/map2/map_insdel_func6.cpp +++ /dev/null @@ -1,9 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_insdel_func.h" - -namespace map2 { - CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_StripedMap ) - CDSUNIT_TEST_StripedMap - CPPUNIT_TEST_SUITE_END_PART() -} // namespace map2 diff --git a/tests/unit/map2/map_insdel_func7.cpp b/tests/unit/map2/map_insdel_func7.cpp deleted file mode 100644 index 10fdfad6..00000000 --- a/tests/unit/map2/map_insdel_func7.cpp +++ /dev/null @@ -1,9 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_insdel_func.h" - -namespace map2 { - CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_RefinableMap ) - CDSUNIT_TEST_RefinableMap - CPPUNIT_TEST_SUITE_END_PART() -} // namespace map2 diff --git a/tests/unit/map2/map_insdel_func8.cpp b/tests/unit/map2/map_insdel_func8.cpp deleted file mode 100644 index b8901950..00000000 --- a/tests/unit/map2/map_insdel_func8.cpp +++ /dev/null @@ -1,9 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_insdel_func.h" - -namespace map2 { - CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_CuckooMap ) - CDSUNIT_TEST_CuckooMap - CPPUNIT_TEST_SUITE_END_PART() -} // namespace map2 diff --git a/tests/unit/map2/map_insdel_func_bronsonavltree.cpp b/tests/unit/map2/map_insdel_func_bronsonavltree.cpp new file mode 100644 index 00000000..30d277d3 --- /dev/null +++ b/tests/unit/map2/map_insdel_func_bronsonavltree.cpp @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#include "map2/map_insdel_func.h" + +namespace map2 { + CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_BronsonAVLTreeMap ) + CDSUNIT_TEST_BronsonAVLTreeMap + CPPUNIT_TEST_SUITE_END_PART() +} // namespace map2 diff --git a/tests/unit/map2/map_insdel_func_cuckoo.cpp b/tests/unit/map2/map_insdel_func_cuckoo.cpp new file mode 100644 index 00000000..b8901950 --- /dev/null +++ b/tests/unit/map2/map_insdel_func_cuckoo.cpp @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#include "map2/map_insdel_func.h" + +namespace map2 { + CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_CuckooMap ) + CDSUNIT_TEST_CuckooMap + CPPUNIT_TEST_SUITE_END_PART() +} // namespace map2 diff --git a/tests/unit/map2/map_insdel_func_ellentree.cpp b/tests/unit/map2/map_insdel_func_ellentree.cpp new file mode 100644 index 00000000..1533d352 --- /dev/null +++ b/tests/unit/map2/map_insdel_func_ellentree.cpp @@ -0,0 +1,10 @@ +//$$CDS-header$$ + +#include "map2/map_insdel_func.h" + +namespace map2 { + CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_EllenBinTreeMap ) + CDSUNIT_TEST_EllenBinTreeMap + CPPUNIT_TEST_SUITE_END_PART() +} // namespace map2 + diff --git a/tests/unit/map2/map_insdel_func_michael.cpp b/tests/unit/map2/map_insdel_func_michael.cpp new file mode 100644 index 00000000..41e1a7cf --- /dev/null +++ b/tests/unit/map2/map_insdel_func_michael.cpp @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#include "map2/map_insdel_func.h" + +namespace map2 { + CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_MichaelMap ) + CDSUNIT_TEST_MichaelMap + CPPUNIT_TEST_SUITE_END_PART() +} // namespace map2 diff --git a/tests/unit/map2/map_insdel_func_refinable.cpp b/tests/unit/map2/map_insdel_func_refinable.cpp new file mode 100644 index 00000000..10fdfad6 --- /dev/null +++ b/tests/unit/map2/map_insdel_func_refinable.cpp @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#include "map2/map_insdel_func.h" + +namespace map2 { + CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_RefinableMap ) + CDSUNIT_TEST_RefinableMap + CPPUNIT_TEST_SUITE_END_PART() +} // namespace map2 diff --git a/tests/unit/map2/map_insdel_func_skip.cpp b/tests/unit/map2/map_insdel_func_skip.cpp new file mode 100644 index 00000000..9cec610e --- /dev/null +++ b/tests/unit/map2/map_insdel_func_skip.cpp @@ -0,0 +1,10 @@ +//$$CDS-header$$ + +#include "map2/map_insdel_func.h" + +namespace map2 { + CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_SkipListMap ) + CDSUNIT_TEST_SkipListMap + CPPUNIT_TEST_SUITE_END_PART() +} // namespace map2 + diff --git a/tests/unit/map2/map_insdel_func_split.cpp b/tests/unit/map2/map_insdel_func_split.cpp new file mode 100644 index 00000000..da1c3fac --- /dev/null +++ b/tests/unit/map2/map_insdel_func_split.cpp @@ -0,0 +1,10 @@ +//$$CDS-header$$ + +#include "map2/map_insdel_func.h" + +namespace map2 { + CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_SplitList ) + CDSUNIT_TEST_SplitList + CPPUNIT_TEST_SUITE_END_PART() +} // namespace map2 + diff --git a/tests/unit/map2/map_insdel_func_striped.cpp b/tests/unit/map2/map_insdel_func_striped.cpp new file mode 100644 index 00000000..f6841183 --- /dev/null +++ b/tests/unit/map2/map_insdel_func_striped.cpp @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#include "map2/map_insdel_func.h" + +namespace map2 { + CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_StripedMap ) + CDSUNIT_TEST_StripedMap + CPPUNIT_TEST_SUITE_END_PART() +} // namespace map2