a2c4126db5f55970bd9f22d4dfbece7eabf2fe4a
[junction.git] / test / junction_parallel_driver.cpp
1 #include "test.h"
2
3 namespace junction_test {
4
5 class JunctionMapInsDelFindTest_Parallel : public cds_test::stress_fixture {
6 protected:
7   static unsigned s_nInsertPercentage;
8   static unsigned s_nDeletePercentage;
9   static size_t s_nGCFrequency; // Run GC after "s_nGCFrequency" operations.
10   static size_t s_nThreadCount;
11   static size_t s_nMapKeyRange;
12   static size_t s_nCrudeMapCapacity;
13
14   enum actions { do_find, do_insert, do_delete };
15   static const unsigned int kShuffleSize = 100;
16   static actions s_arrShuffle[kShuffleSize];
17
18   static size_t s_nCrudePassCount;
19   static size_t s_nGrampaPassCount;
20   static size_t s_nLinearPassCount;
21   static size_t s_nLeapfrogPassCount;
22
23   static void InitShuffleArray() {
24     // Build an array of shuffled actions.
25     EXPECT_LE(s_nInsertPercentage + s_nDeletePercentage, 100);
26     actions* pFirst = s_arrShuffle;
27     actions* pLast = s_arrShuffle + s_nInsertPercentage;
28     std::fill(pFirst, pLast, do_insert);
29     pFirst = pLast;
30     pLast += s_nDeletePercentage;
31     std::fill(pFirst, pLast, do_delete);
32     pFirst = pLast;
33     pLast = s_arrShuffle + sizeof(s_arrShuffle) / sizeof(s_arrShuffle[0]);
34     if (pFirst < pLast) {
35       std::fill(pFirst, pLast, do_find);
36     }
37     std::random_device rd;
38     std::mt19937 g(rd());
39     std::shuffle(s_arrShuffle, pLast, g);
40   }
41
42   static void SetUpTestCase() {
43     InitShuffleArray();
44     const cds_test::config& cfg = get_config("ParallelJunction");
45     GetConfigNonZeroExpected(InsertPercentage, 5);
46     GetConfigNonZeroExpected(DeletePercentage, 5);
47     GetConfigNonZeroExpected(ThreadCount, 4);
48     GetConfigNonZeroExpected(MapKeyRange, 20000);
49     GetConfigNonZeroExpected(CrudeMapCapacity, s_nMapKeyRange * 64);
50     GetConfigNonZeroExpected(GCFrequency, 1500);
51     GetConfigNonZeroExpected(CrudePassCount, 1500000000);
52     GetConfigNonZeroExpected(GrampaPassCount, 650000000);
53     GetConfigNonZeroExpected(LinearPassCount, 900000000);
54     GetConfigNonZeroExpected(LeapfrogPassCount, 850000000);
55   }
56
57   template <typename Map>
58   static void run_test(Map* map, size_t pass_count, size_t* inserted_num,
59                        size_t* deleted_num) {
60     auto qsbrContext = junction::DefaultQSBR.createContext();
61
62     std::random_device rd;
63     std::mt19937 gen(rd());
64     std::uniform_int_distribution<size_t> dis(2, s_nMapKeyRange);
65
66     unsigned action_index = 0;
67     size_t nInsertedNum = 0;
68     size_t nDeletedNum = 0;
69     size_t nFindSuccess = 0;
70     size_t nOperations = 0;
71
72     for (size_t count = 0; count < pass_count; count++) {
73       // The number to operate on the map.
74       size_t key = dis(gen);
75       switch (s_arrShuffle[action_index]) {
76         case do_insert: {
77           size_t val = dis(gen);
78           if (map_insert(map, key, val)) {
79             nInsertedNum++;
80           }
81           break;
82         }
83         case do_delete: {
84           if (map_delete(map, key)) {
85             nDeletedNum++;
86           }
87           break;
88         }
89         case do_find: {
90           if (map_find(map, key)) {
91             ++nFindSuccess;
92           }
93           break;
94         }
95         default: { break; }
96       }
97       if (++action_index >= kShuffleSize) {
98         action_index = 0;
99       }
100       if (++nOperations > s_nGCFrequency) {
101         junction::DefaultQSBR.update(qsbrContext);
102         nOperations = 0;
103       }
104     }
105     junction::DefaultQSBR.update(qsbrContext);
106     junction::DefaultQSBR.destroyContext(qsbrContext);
107     *inserted_num = nInsertedNum;
108     *deleted_num = nDeletedNum;
109   }
110 };
111
112 size_t JunctionMapInsDelFindTest_Parallel::s_nThreadCount;
113 size_t JunctionMapInsDelFindTest_Parallel::s_nMapKeyRange;
114 size_t JunctionMapInsDelFindTest_Parallel::s_nCrudeMapCapacity;
115 size_t JunctionMapInsDelFindTest_Parallel::s_nGCFrequency;
116 unsigned JunctionMapInsDelFindTest_Parallel::s_nInsertPercentage;
117 unsigned JunctionMapInsDelFindTest_Parallel::s_nDeletePercentage;
118 const unsigned int JunctionMapInsDelFindTest_Parallel::kShuffleSize;
119 JunctionMapInsDelFindTest_Parallel::actions JunctionMapInsDelFindTest_Parallel::
120     s_arrShuffle[JunctionMapInsDelFindTest_Parallel::kShuffleSize];
121 size_t JunctionMapInsDelFindTest_Parallel::s_nCrudePassCount;
122 size_t JunctionMapInsDelFindTest_Parallel::s_nGrampaPassCount;
123 size_t JunctionMapInsDelFindTest_Parallel::s_nLinearPassCount;
124 size_t JunctionMapInsDelFindTest_Parallel::s_nLeapfrogPassCount;
125
126 #define JunctionThreading(map_type, pass_count)                                \
127   std::unique_ptr<std::thread[]> threads(new std::thread[s_nThreadCount]);     \
128   std::unique_ptr<size_t[]> inserted_nums(new size_t[s_nThreadCount]);         \
129   std::unique_ptr<size_t[]> deleted_nums(new size_t[s_nThreadCount]);          \
130   for (size_t i = 0; i < s_nThreadCount; i++) {                                \
131     threads[i] = std::thread(run_test<map_type>, map.get(), pass_count,        \
132                              &inserted_nums[i], &deleted_nums[i]);             \
133   }                                                                            \
134   size_t inserted_sum = 0;                                                     \
135   size_t deleted_sum = 0;                                                      \
136   for (size_t i = 0; i < s_nThreadCount; i++) {                                \
137     threads[i].join();                                                         \
138     inserted_sum += inserted_nums[i];                                          \
139     deleted_sum += deleted_nums[i];                                            \
140   }                                                                            \
141   EXPECT_LE(deleted_sum, inserted_sum);
142
143 TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapCrude) {
144   std::unique_ptr<CrudeMap> map(new CrudeMap(s_nCrudeMapCapacity));
145   JunctionThreading(CrudeMap, s_nCrudePassCount);
146 }
147
148 TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapLeapfrog) {
149   std::unique_ptr<LeapfrogMap> map(new LeapfrogMap());
150   JunctionThreading(LeapfrogMap, s_nLeapfrogPassCount);
151 }
152
153 TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapLinear) {
154   std::unique_ptr<LinearMap> map(new LinearMap());
155   JunctionThreading(LinearMap, s_nLinearPassCount);
156 }
157
158 TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapGrampa) {
159   std::unique_ptr<GrampaMap> map(new GrampaMap());
160   JunctionThreading(GrampaMap, s_nGrampaPassCount);
161 }
162
163 } // namespace junction_test