X-Git-Url: http://plrg.eecs.uci.edu/git/?p=junction.git;a=blobdiff_plain;f=test%2Fjunction_parallel_driver.cpp;h=b6f74f6fb2213d327ae68250ae7ba58e93778290;hp=d0164387950f63a585733dde3ce66a531ec5ceb6;hb=a5c4f9abb37cd877dbb7be486657e9dca281274d;hpb=176b53dafc01aa30b9128db59fd3a234fff1198d;ds=sidebyside diff --git a/test/junction_parallel_driver.cpp b/test/junction_parallel_driver.cpp index d016438..b6f74f6 100644 --- a/test/junction_parallel_driver.cpp +++ b/test/junction_parallel_driver.cpp @@ -1,158 +1,233 @@ -#include -#include -#include #include #include #include #include -#include -#include +#include +#include + +#include +#include +#include +#include +#include namespace junction_test { -class JunctionMapInsDelFindTest : public ::testing::Test { +class JunctionMapInsDelFindTest_Parallel : public cds_test::stress_fixture { protected: typedef junction::ConcurrentMap_Grampa GrampaMap; typedef junction::ConcurrentMap_Linear LinearMap; typedef junction::ConcurrentMap_Leapfrog LeapfrogMap; typedef junction::ConcurrentMap_Crude CrudeMap; - static const unsigned s_nInsertPercentage = 10; - // Run GC after "kGCFrequency" operations. - static const size_t kGCFrequency = 3000; - static const size_t kLeapfrogGCFrequency = 1500; + static unsigned s_nInsertPercentage; + static unsigned s_nDeletePercentage; + static size_t s_nGCFrequency; // Run GC after "s_nGCFrequency" operations. + static size_t s_nThreadCount; + static size_t s_nMapKeyRange; + static size_t s_nCrudeMapCapacity; + + enum actions { do_find, do_insert, do_delete }; + static const unsigned int kShuffleSize = 100; + static actions s_arrShuffle[kShuffleSize]; + + static size_t s_nCrudePassCount; + static size_t s_nGrampaPassCount; + static size_t s_nLinearPassCount; + static size_t s_nLeapfrogPassCount; + + static void InitShuffleArray() { + // Build an array of shuffled actions. + EXPECT_LE(s_nInsertPercentage + s_nDeletePercentage, 100); + actions* pFirst = s_arrShuffle; + actions* pLast = s_arrShuffle + s_nInsertPercentage; + std::fill(pFirst, pLast, do_insert); + pFirst = pLast; + pLast += s_nDeletePercentage; + std::fill(pFirst, pLast, do_delete); + pFirst = pLast; + pLast = s_arrShuffle + sizeof(s_arrShuffle) / sizeof(s_arrShuffle[0]); + if (pFirst < pLast) { + std::fill(pFirst, pLast, do_find); + } + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(s_arrShuffle, pLast, g); + } - static const size_t kCrudeMapSize = 10000; - static const size_t kCrudePassCount = 400000; + static void SetUpTestCase() { + InitShuffleArray(); + const cds_test::config& cfg = get_config("ParallelJunction"); + GetConfigNonZeroExpected(InsertPercentage, 5); + GetConfigNonZeroExpected(DeletePercentage, 5); + GetConfigNonZeroExpected(ThreadCount, 4); + GetConfigNonZeroExpected(MapKeyRange, 20000); + GetConfigNonZeroExpected(CrudeMapCapacity, s_nMapKeyRange * 64); + GetConfigNonZeroExpected(GCFrequency, 1500); + GetConfigNonZeroExpected(CrudePassCount, 1500000000); + GetConfigNonZeroExpected(GrampaPassCount, 650000000); + GetConfigNonZeroExpected(LinearPassCount, 900000000); + GetConfigNonZeroExpected(LeapfrogPassCount, 850000000); + } - static const size_t kGrampaMapSize = 20000; - static const size_t kGrampaPassCount = 60000; + template + static bool map_insert(Map* map, Key key, Value value) { + auto iter = map->insertOrFind(key); + if (!iter.getValue() || iter.getValue() != value) { + // Insert/update the pair + iter.assignValue(value); + return true; + } else { + return false; + } + } - static const size_t kLinearMapSize = 20000; - static const size_t kLinearPassCount = 70000; + template + static bool map_delete(Map* map, Key key) { + auto iter = map->find(key); + if (iter.getValue()) { + iter.eraseValue(); + return true; + } else { + return false; + } + } - static const size_t kLeapfrogMapSize = 20000; - static const size_t kLeapfrogPassCount = 75000; + template + static bool map_find(Map* map, Key key) { + auto iter = map->find(key); + if (iter.getValue()) { + return true; + } else { + return false; + } + } - static void SetUpTestCase() {} + // Specialization for CrudeMap + template + static bool map_insert(CrudeMap* map, Key key, Value value) { + auto old_val = map->get(key); + if (!old_val || old_val != value) { + map->assign(key, value); + return true; + } else { + return false; + } + } - template - static void run_test(size_t map_size, size_t pass_count, - size_t gc_frequency) { - size_t nInsertedNum = 0; - size_t nFindSuccess = 0; - size_t nOperations = 0; - std::unique_ptr map(new Map()); - auto qsbrContext = junction::DefaultQSBR.createContext(); - for (size_t count = 0; count < pass_count; count++) { - for (size_t i = 0; i < map_size; ++i) { - // The number to operate on the map. - size_t n = map_size + i; - // Insert - if (i % s_nInsertPercentage == 1) { - auto iter = map->insertOrFind(i); - if (!iter.getValue()) { - iter.assignValue(n); - nInsertedNum++; - // std::cout << "Inserted" << i << "\n"; - } - } - // Find - { - auto iter = map->find(i); - if (iter.getValue()) { - ++nFindSuccess; - // std::cout << "Found" << i << "\n"; - } - } - // Delete - if (i % s_nInsertPercentage == 1) { - auto iter = map->find(i); - if (iter.getValue()) { - iter.eraseValue(); - // std::cout << "Erased" << i << "\n"; - } - } - if (++nOperations > gc_frequency) { - junction::DefaultQSBR.update(qsbrContext); - nOperations = 0; - } - } + template static bool map_delete(CrudeMap* map, Key key) { + if (!map->get(key)) { + map->assign(key, ((Key)0)); + return true; + } else { + return false; } - junction::DefaultQSBR.update(qsbrContext); - junction::DefaultQSBR.destroyContext(qsbrContext); - EXPECT_EQ(nFindSuccess, nInsertedNum); } - template - void run_crude_map(size_t map_size, size_t pass_count, size_t gc_frequency) { + template static bool map_find(CrudeMap* map, Key key) { + return map->get(key) != ((Key)0); + } + + template static void run_test(Map* map, size_t pass_count) { + auto qsbrContext = junction::DefaultQSBR.createContext(); + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(2, s_nMapKeyRange); + + unsigned action_index = 0; size_t nInsertedNum = 0; size_t nFindSuccess = 0; size_t nOperations = 0; - // Seems like the crude map won't resize, so better have a large enough - // capacity. - std::unique_ptr map(new Map(map_size * 32)); - auto qsbrContext = junction::DefaultQSBR.createContext(); + for (size_t count = 0; count < pass_count; count++) { - for (size_t i = 0; i < map_size; ++i) { - // The number to operate on the map. - size_t n = map_size + i; - // Insert - if (i % s_nInsertPercentage == 1) { - map->assign(i, n); - nInsertedNum++; - // std::cout << "Inserted" << i << "\n"; - } - // Find - { - if (map->get(i)) { - ++nFindSuccess; - // std::cout << "Found" << i << "\n"; + // The number to operate on the map. + size_t key = dis(gen); + switch (s_arrShuffle[action_index]) { + case do_insert: { + size_t val = dis(gen); + if (map_insert(map, key, val)) { + nInsertedNum++; } + break; } - // Delete - if (i % s_nInsertPercentage == 1) { - if (map->get(i)) { - map->assign(n, 0); - // std::cout << "Erased" << i << "\n"; - } + case do_delete: { + map_delete(map, key); + break; } - if (++nOperations > gc_frequency) { - junction::DefaultQSBR.update(qsbrContext); - nOperations = 0; + case do_find: { + if (map_find(map, key)) { + ++nFindSuccess; + } + break; } + default: { break; } + } + if (++action_index >= kShuffleSize) { + action_index = 0; + } + if (++nOperations > s_nGCFrequency) { + junction::DefaultQSBR.update(qsbrContext); + nOperations = 0; } } junction::DefaultQSBR.update(qsbrContext); junction::DefaultQSBR.destroyContext(qsbrContext); - - EXPECT_EQ(nFindSuccess, nInsertedNum); } }; -TEST_F(JunctionMapInsDelFindTest, JunctionMapCrude) { - run_crude_map(kCrudeMapSize, kCrudePassCount, kGCFrequency); +size_t JunctionMapInsDelFindTest_Parallel::s_nThreadCount; +size_t JunctionMapInsDelFindTest_Parallel::s_nMapKeyRange; +size_t JunctionMapInsDelFindTest_Parallel::s_nCrudeMapCapacity; +size_t JunctionMapInsDelFindTest_Parallel::s_nGCFrequency; +unsigned JunctionMapInsDelFindTest_Parallel::s_nInsertPercentage; +unsigned JunctionMapInsDelFindTest_Parallel::s_nDeletePercentage; +const unsigned int JunctionMapInsDelFindTest_Parallel::kShuffleSize; +JunctionMapInsDelFindTest_Parallel::actions JunctionMapInsDelFindTest_Parallel:: + s_arrShuffle[JunctionMapInsDelFindTest_Parallel::kShuffleSize]; +size_t JunctionMapInsDelFindTest_Parallel::s_nCrudePassCount; +size_t JunctionMapInsDelFindTest_Parallel::s_nGrampaPassCount; +size_t JunctionMapInsDelFindTest_Parallel::s_nLinearPassCount; +size_t JunctionMapInsDelFindTest_Parallel::s_nLeapfrogPassCount; + +#define JunctionThreading(map_type, pass_count) \ + std::unique_ptr threads(new std::thread[s_nThreadCount]); \ + for (size_t i = 0; i < s_nThreadCount; i++) { \ + threads[i] = std::thread(run_test, map.get(), pass_count); \ + } \ + for (size_t i = 0; i < s_nThreadCount; i++) { \ + threads[i].join(); \ + } + +TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapCrude) { + std::unique_ptr map(new CrudeMap(s_nCrudeMapCapacity)); + JunctionThreading(CrudeMap, s_nCrudePassCount); } -TEST_F(JunctionMapInsDelFindTest, JunctionMapLeapfrog) { - run_test(kLeapfrogMapSize, kLeapfrogPassCount, - kLeapfrogGCFrequency); +TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapLeapfrog) { + std::unique_ptr map(new LeapfrogMap()); + JunctionThreading(LeapfrogMap, s_nLeapfrogPassCount); } -TEST_F(JunctionMapInsDelFindTest, JunctionMapLinear) { - run_test(kLinearMapSize, kLinearPassCount, kGCFrequency); +TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapLinear) { + std::unique_ptr map(new LinearMap()); + JunctionThreading(LinearMap, s_nLinearPassCount); } -TEST_F(JunctionMapInsDelFindTest, JunctionMapGrampa) { - run_test(kGrampaMapSize, kGrampaPassCount, kGCFrequency); +TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapGrampa) { + std::unique_ptr map(new GrampaMap()); + JunctionThreading(GrampaMap, s_nGrampaPassCount); } } // namespace junction_test int main(int argc, char** argv) { + // Read test config file + cds_test::init_config(argc, argv); + // Init Google test ::testing::InitGoogleTest(&argc, argv); int result = RUN_ALL_TESTS(); - return 0; + return result; }