1 #include <junction/ConcurrentMap_Crude.h>
2 #include <junction/ConcurrentMap_Grampa.h>
3 #include <junction/ConcurrentMap_Leapfrog.h>
4 #include <junction/ConcurrentMap_Linear.h>
6 #include <cds_test/stress_test.h>
7 #include <cds_test/stress_test_util.h>
15 namespace junction_test {
17 class JunctionMapInsDelFindTest_Parallel : public cds_test::stress_fixture {
19 typedef junction::ConcurrentMap_Grampa<size_t, size_t> GrampaMap;
20 typedef junction::ConcurrentMap_Linear<size_t, size_t> LinearMap;
21 typedef junction::ConcurrentMap_Leapfrog<size_t, size_t> LeapfrogMap;
22 typedef junction::ConcurrentMap_Crude<size_t, size_t> CrudeMap;
24 static unsigned s_nInsertPercentage;
25 static unsigned s_nDeletePercentage;
26 static size_t s_nGCFrequency; // Run GC after "s_nGCFrequency" operations.
27 static size_t s_nThreadCount;
28 static size_t s_nMapKeyRange;
29 static size_t s_nCrudeMapCapacity;
31 enum actions { do_find, do_insert, do_delete };
32 static const unsigned int kShuffleSize = 100;
33 static actions s_arrShuffle[kShuffleSize];
35 static size_t s_nCrudePassCount;
36 static size_t s_nGrampaPassCount;
37 static size_t s_nLinearPassCount;
38 static size_t s_nLeapfrogPassCount;
40 static void InitShuffleArray() {
41 // Build an array of shuffled actions.
42 EXPECT_LE(s_nInsertPercentage + s_nDeletePercentage, 100);
43 actions* pFirst = s_arrShuffle;
44 actions* pLast = s_arrShuffle + s_nInsertPercentage;
45 std::fill(pFirst, pLast, do_insert);
47 pLast += s_nDeletePercentage;
48 std::fill(pFirst, pLast, do_delete);
50 pLast = s_arrShuffle + sizeof(s_arrShuffle) / sizeof(s_arrShuffle[0]);
52 std::fill(pFirst, pLast, do_find);
54 std::random_device rd;
56 std::shuffle(s_arrShuffle, pLast, g);
59 static void SetUpTestCase() {
61 const cds_test::config& cfg = get_config("ParallelJunction");
62 GetConfigNonZeroExpected(InsertPercentage, 5);
63 GetConfigNonZeroExpected(DeletePercentage, 5);
64 GetConfigNonZeroExpected(ThreadCount, 4);
65 GetConfigNonZeroExpected(MapKeyRange, 20000);
66 GetConfigNonZeroExpected(CrudeMapCapacity, s_nMapKeyRange * 64);
67 GetConfigNonZeroExpected(GCFrequency, 1500);
68 GetConfigNonZeroExpected(CrudePassCount, 1500000000);
69 GetConfigNonZeroExpected(GrampaPassCount, 650000000);
70 GetConfigNonZeroExpected(LinearPassCount, 900000000);
71 GetConfigNonZeroExpected(LeapfrogPassCount, 850000000);
74 template <typename Map, typename Key, typename Value>
75 static bool map_insert(Map* map, Key key, Value value) {
76 auto iter = map->insertOrFind(key);
77 if (!iter.getValue() || iter.getValue() != value) {
78 // Insert/update the <key,value> pair
79 iter.assignValue(value);
86 template <typename Map, typename Key>
87 static bool map_delete(Map* map, Key key) {
88 auto iter = map->find(key);
89 if (iter.getValue()) {
97 template <typename Map, typename Key>
98 static bool map_find(Map* map, Key key) {
99 auto iter = map->find(key);
100 if (iter.getValue()) {
107 // Specialization for CrudeMap
108 template <typename Key, typename Value>
109 static bool map_insert(CrudeMap* map, Key key, Value value) {
110 auto old_val = map->get(key);
111 if (!old_val || old_val != value) {
112 map->assign(key, value);
119 template <typename Key> static bool map_delete(CrudeMap* map, Key key) {
120 if (!map->get(key)) {
121 map->assign(key, ((Key)0));
128 template <typename Key> static bool map_find(CrudeMap* map, Key key) {
129 return map->get(key) != ((Key)0);
132 template <typename Map> static void run_test(Map* map, size_t pass_count) {
133 auto qsbrContext = junction::DefaultQSBR.createContext();
135 std::random_device rd;
136 std::mt19937 gen(rd());
137 std::uniform_int_distribution<size_t> dis(2, s_nMapKeyRange);
139 unsigned action_index = 0;
140 size_t nInsertedNum = 0;
141 size_t nFindSuccess = 0;
142 size_t nOperations = 0;
144 for (size_t count = 0; count < pass_count; count++) {
145 // The number to operate on the map.
146 size_t key = dis(gen);
147 switch (s_arrShuffle[action_index]) {
149 size_t val = dis(gen);
150 if (map_insert(map, key, val)) {
156 map_delete(map, key);
160 if (map_find(map, key)) {
167 if (++action_index >= kShuffleSize) {
170 if (++nOperations > s_nGCFrequency) {
171 junction::DefaultQSBR.update(qsbrContext);
175 junction::DefaultQSBR.update(qsbrContext);
176 junction::DefaultQSBR.destroyContext(qsbrContext);
180 size_t JunctionMapInsDelFindTest_Parallel::s_nThreadCount;
181 size_t JunctionMapInsDelFindTest_Parallel::s_nMapKeyRange;
182 size_t JunctionMapInsDelFindTest_Parallel::s_nCrudeMapCapacity;
183 size_t JunctionMapInsDelFindTest_Parallel::s_nGCFrequency;
184 unsigned JunctionMapInsDelFindTest_Parallel::s_nInsertPercentage;
185 unsigned JunctionMapInsDelFindTest_Parallel::s_nDeletePercentage;
186 const unsigned int JunctionMapInsDelFindTest_Parallel::kShuffleSize;
187 JunctionMapInsDelFindTest_Parallel::actions JunctionMapInsDelFindTest_Parallel::
188 s_arrShuffle[JunctionMapInsDelFindTest_Parallel::kShuffleSize];
189 size_t JunctionMapInsDelFindTest_Parallel::s_nCrudePassCount;
190 size_t JunctionMapInsDelFindTest_Parallel::s_nGrampaPassCount;
191 size_t JunctionMapInsDelFindTest_Parallel::s_nLinearPassCount;
192 size_t JunctionMapInsDelFindTest_Parallel::s_nLeapfrogPassCount;
194 #define JunctionThreading(map_type, pass_count) \
195 std::unique_ptr<std::thread[]> threads(new std::thread[s_nThreadCount]); \
196 for (size_t i = 0; i < s_nThreadCount; i++) { \
197 threads[i] = std::thread(run_test<map_type>, map.get(), pass_count); \
199 for (size_t i = 0; i < s_nThreadCount; i++) { \
203 TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapCrude) {
204 std::unique_ptr<CrudeMap> map(new CrudeMap(s_nCrudeMapCapacity));
205 JunctionThreading(CrudeMap, s_nCrudePassCount);
208 TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapLeapfrog) {
209 std::unique_ptr<LeapfrogMap> map(new LeapfrogMap());
210 JunctionThreading(LeapfrogMap, s_nLeapfrogPassCount);
213 TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapLinear) {
214 std::unique_ptr<LinearMap> map(new LinearMap());
215 JunctionThreading(LinearMap, s_nLinearPassCount);
218 TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapGrampa) {
219 std::unique_ptr<GrampaMap> map(new GrampaMap());
220 JunctionThreading(GrampaMap, s_nGrampaPassCount);
223 } // namespace junction_test
225 int main(int argc, char** argv) {
226 // Read test config file
227 cds_test::init_config(argc, argv);
230 ::testing::InitGoogleTest(&argc, argv);
231 int result = RUN_ALL_TESTS();