-#include <junction/ConcurrentMap_Crude.h>
-#include <junction/ConcurrentMap_Grampa.h>
-#include <junction/ConcurrentMap_Leapfrog.h>
-#include <junction/ConcurrentMap_Linear.h>
-
-#include <cds_test/stress_test.h>
-#include <cds_test/stress_test_util.h>
-
-#include <algorithm>
-#include <iostream>
-#include <memory>
-#include <random>
-#include <thread>
+#include "test.h"
namespace junction_test {
class JunctionMapInsDelFindTest_Parallel : public cds_test::stress_fixture {
protected:
- typedef junction::ConcurrentMap_Grampa<size_t, size_t> GrampaMap;
- typedef junction::ConcurrentMap_Linear<size_t, size_t> LinearMap;
- typedef junction::ConcurrentMap_Leapfrog<size_t, size_t> LeapfrogMap;
- typedef junction::ConcurrentMap_Crude<size_t, size_t> CrudeMap;
-
static unsigned s_nInsertPercentage;
static unsigned s_nDeletePercentage;
static size_t s_nGCFrequency; // Run GC after "s_nGCFrequency" operations.
GetConfigNonZeroExpected(DeletePercentage, 5);
GetConfigNonZeroExpected(ThreadCount, 4);
GetConfigNonZeroExpected(MapKeyRange, 20000);
- GetConfigNonZeroExpected(CrudeMapCapacity, s_nMapKeyRange * 64);
+ // CrudeMap may need a big enough capacity in case may insertion operations
+ // got jammed up.
+ GetConfigNonZeroExpected(CrudeMapCapacity, s_nMapKeyRange * 1024);
GetConfigNonZeroExpected(GCFrequency, 1500);
GetConfigNonZeroExpected(CrudePassCount, 1500000000);
GetConfigNonZeroExpected(GrampaPassCount, 650000000);
GetConfigNonZeroExpected(LeapfrogPassCount, 850000000);
}
- template <typename Map, typename Key, typename Value>
- static bool map_insert(Map* map, Key key, Value value) {
- auto iter = map->insertOrFind(key);
- if (!iter.getValue() || iter.getValue() != value) {
- // Insert/update the <key,value> pair
- iter.assignValue(value);
- return true;
- } else {
- return false;
- }
- }
-
- template <typename Map, typename Key>
- static bool map_delete(Map* map, Key key) {
- auto iter = map->find(key);
- if (iter.getValue()) {
- iter.eraseValue();
- return true;
- } else {
- return false;
- }
- }
-
- template <typename Map, typename Key>
- static bool map_find(Map* map, Key key) {
- auto iter = map->find(key);
- if (iter.getValue()) {
- return true;
- } else {
- return false;
- }
- }
-
- // Specialization for CrudeMap
- template <typename Key, typename Value>
- 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 <typename Key> static bool map_delete(CrudeMap* map, Key key) {
- if (!map->get(key)) {
- map->assign(key, ((Key)0));
- return true;
- } else {
- return false;
- }
- }
-
- template <typename Key> static bool map_find(CrudeMap* map, Key key) {
- return map->get(key) != ((Key)0);
- }
-
- template <typename Map> static void run_test(Map* map, size_t pass_count) {
+ template <typename Map>
+ static void run_test(Map* map, size_t pass_count, size_t* inserted_num,
+ size_t* deleted_num) {
auto qsbrContext = junction::DefaultQSBR.createContext();
std::random_device rd;
unsigned action_index = 0;
size_t nInsertedNum = 0;
+ size_t nDeletedNum = 0;
size_t nFindSuccess = 0;
size_t nOperations = 0;
break;
}
case do_delete: {
- map_delete(map, key);
+ if (map_delete(map, key)) {
+ nDeletedNum++;
+ }
break;
}
case do_find: {
}
junction::DefaultQSBR.update(qsbrContext);
junction::DefaultQSBR.destroyContext(qsbrContext);
+ *inserted_num = nInsertedNum;
+ *deleted_num = nDeletedNum;
+ }
+
+ template <typename Map>
+ void JunctionThreading(Map* map, size_t pass_count) {
+ std::unique_ptr<std::thread[]> threads(new std::thread[s_nThreadCount]);
+ std::unique_ptr<size_t[]> inserted_nums(new size_t[s_nThreadCount]);
+ std::unique_ptr<size_t[]> deleted_nums(new size_t[s_nThreadCount]);
+ for (size_t i = 0; i < s_nThreadCount; i++) {
+ threads[i] = std::thread(run_test<Map>, map, pass_count,
+ &inserted_nums[i], &deleted_nums[i]);
+ }
+ size_t inserted_sum = 0;
+ size_t deleted_sum = 0;
+ for (size_t i = 0; i < s_nThreadCount; i++) {
+ threads[i].join();
+ inserted_sum += inserted_nums[i];
+ deleted_sum += deleted_nums[i];
+ }
+ EXPECT_LE(deleted_sum, inserted_sum);
}
};
size_t JunctionMapInsDelFindTest_Parallel::s_nLinearPassCount;
size_t JunctionMapInsDelFindTest_Parallel::s_nLeapfrogPassCount;
-#define JunctionThreading(map_type, pass_count) \
- std::unique_ptr<std::thread[]> threads(new std::thread[s_nThreadCount]); \
- for (size_t i = 0; i < s_nThreadCount; i++) { \
- threads[i] = std::thread(run_test<map_type>, map.get(), pass_count); \
- } \
- for (size_t i = 0; i < s_nThreadCount; i++) { \
- threads[i].join(); \
- }
-
TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapCrude) {
std::unique_ptr<CrudeMap> map(new CrudeMap(s_nCrudeMapCapacity));
- JunctionThreading(CrudeMap, s_nCrudePassCount);
+ JunctionThreading(map.get(), s_nCrudePassCount);
}
TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapLeapfrog) {
std::unique_ptr<LeapfrogMap> map(new LeapfrogMap());
- JunctionThreading(LeapfrogMap, s_nLeapfrogPassCount);
+ JunctionThreading(map.get(), s_nLeapfrogPassCount);
}
TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapLinear) {
std::unique_ptr<LinearMap> map(new LinearMap());
- JunctionThreading(LinearMap, s_nLinearPassCount);
+ JunctionThreading(map.get(), s_nLinearPassCount);
}
TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapGrampa) {
std::unique_ptr<GrampaMap> map(new GrampaMap());
- JunctionThreading(GrampaMap, s_nGrampaPassCount);
+ JunctionThreading(map.get(), 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 result;
-}