b9f5d8f07e82f094b007f3b540ea6508dc128a33
[junction.git] / test / junction_parallel_driver.cpp
1 #include <junction/ConcurrentMap_Crude.h>
2 #include <junction/ConcurrentMap_Grampa.h>
3 #include <junction/ConcurrentMap_Leapfrog.h>
4 #include <junction/ConcurrentMap_Linear.h>
5
6 #include <gtest/gtest.h>
7
8 #include <algorithm>
9 #include <memory>
10 #include <random>
11
12 namespace junction_test {
13
14 class JunctionMapInsDelFindTest_Parallel : public ::testing::Test {
15 protected:
16   typedef junction::ConcurrentMap_Grampa<size_t, size_t> GrampaMap;
17   typedef junction::ConcurrentMap_Linear<size_t, size_t> LinearMap;
18   typedef junction::ConcurrentMap_Leapfrog<size_t, size_t> LeapfrogMap;
19   typedef junction::ConcurrentMap_Crude<size_t, size_t> CrudeMap;
20
21   static const unsigned s_nInsertPercentage = 5;
22   static const unsigned s_nDeletePercentage = 5;
23
24   // Run GC after "kGCFrequency" operations.
25   const size_t kGCFrequency = 1500;
26   const size_t kMapSize = 20000;
27
28   enum actions { do_find, do_insert, do_delete };
29   static const unsigned int kShuffleSize = 100;
30   static actions s_arrShuffle[kShuffleSize];
31
32   const size_t kCrudePassCount = 400000;
33   const size_t kGrampaPassCount = 60000;
34   const size_t kLinearPassCount = 70000;
35   const size_t kLeapfrogPassCount = 75000;
36
37   static void SetUpTestCase() {
38     // Build an array of shuffled actions.
39     EXPECT_LE(s_nInsertPercentage + s_nDeletePercentage, 100);
40     actions* pFirst = s_arrShuffle;
41     actions* pLast = s_arrShuffle + s_nInsertPercentage;
42     std::fill(pFirst, pLast, do_insert);
43     pFirst = pLast;
44     pLast += s_nDeletePercentage;
45     std::fill(pFirst, pLast, do_delete);
46     pFirst = pLast;
47     pLast = s_arrShuffle + sizeof(s_arrShuffle) / sizeof(s_arrShuffle[0]);
48     if (pFirst < pLast) {
49       std::fill(pFirst, pLast, do_find);
50     }
51     std::random_device rd;
52     std::mt19937 g(rd());
53     std::shuffle(s_arrShuffle, pLast, g);
54   }
55
56   template <typename Map, typename Key, typename Value>
57   static bool map_insert(Map* map, Key key, Value value) {
58     auto iter = map->insertOrFind(key);
59     if (!iter.getValue()) {
60       iter.assignValue(value);
61       return true;
62     } else {
63       return false;
64     }
65   }
66
67   template <typename Map, typename Key>
68   static bool map_delete(Map* map, Key key) {
69     auto iter = map->find(key);
70     if (iter.getValue()) {
71       iter.eraseValue();
72       return true;
73     } else {
74       return false;
75     }
76   }
77
78   template <typename Map, typename Key>
79   static bool map_find(Map* map, Key key) {
80     auto iter = map->find(key);
81     if (iter.getValue()) {
82       return true;
83     } else {
84       return false;
85     }
86   }
87
88   // Specialization for CrudeMap
89   template <typename Key, typename Value>
90   static bool map_insert(CrudeMap* map, Key key, Value value) {
91     if (!map->get(key)) {
92       map->assign(key, value);
93       return true;
94     } else {
95       return false;
96     }
97   }
98
99   template <typename Key> static bool map_delete(CrudeMap* map, Key key) {
100     if (!map->get(key)) {
101       map->assign(key, ((Key)0));
102       return true;
103     } else {
104       return false;
105     }
106   }
107
108   template <typename Key> static bool map_find(CrudeMap* map, Key key) {
109     return map->get(key) != ((Key)0);
110   }
111
112   template <typename Map> void run_test(Map* map, size_t pass_count) {
113     auto qsbrContext = junction::DefaultQSBR.createContext();
114
115     std::random_device rd;
116     std::mt19937 gen(rd());
117     std::uniform_int_distribution<size_t> dis(kMapSize, 2 * kMapSize);
118
119     unsigned action_index = 0;
120     size_t nInsertedNum = 0;
121     size_t nFindSuccess = 0;
122     size_t nOperations = 0;
123
124     for (size_t count = 0; count < pass_count; count++) {
125       for (size_t i = 0; i < kMapSize; ++i) {
126         // The number to operate on the map.
127         size_t n = dis(gen);
128         switch (s_arrShuffle[action_index]) {
129           case do_insert: {
130             if (map_insert(map, n, n)) {
131               nInsertedNum++;
132             }
133             break;
134           }
135           case do_delete: {
136             map_delete(map, n);
137             break;
138           }
139           case do_find: {
140             if (map_find(map, n)) {
141               ++nFindSuccess;
142             }
143             break;
144           }
145           default: { break; }
146         }
147         if (++action_index >= kShuffleSize) {
148           action_index = 0;
149         }
150         if (++nOperations > kGCFrequency) {
151           junction::DefaultQSBR.update(qsbrContext);
152           nOperations = 0;
153         }
154       }
155     }
156     junction::DefaultQSBR.update(qsbrContext);
157     junction::DefaultQSBR.destroyContext(qsbrContext);
158   }
159 };
160
161 const unsigned JunctionMapInsDelFindTest_Parallel::s_nInsertPercentage;
162 const unsigned JunctionMapInsDelFindTest_Parallel::s_nDeletePercentage;
163 const unsigned int JunctionMapInsDelFindTest_Parallel::kShuffleSize;
164 JunctionMapInsDelFindTest_Parallel::actions JunctionMapInsDelFindTest_Parallel::
165     s_arrShuffle[JunctionMapInsDelFindTest_Parallel::kShuffleSize];
166
167 TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapCrude) {
168   std::unique_ptr<CrudeMap> map(new CrudeMap(kMapSize * 32));
169   run_test(map.get(), kCrudePassCount);
170 }
171
172 TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapLeapfrog) {
173   std::unique_ptr<LeapfrogMap> map(new LeapfrogMap());
174   run_test(map.get(), kLeapfrogPassCount);
175 }
176
177 TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapLinear) {
178   std::unique_ptr<LinearMap> map(new LinearMap());
179   run_test(map.get(), kLinearPassCount);
180 }
181
182 TEST_F(JunctionMapInsDelFindTest_Parallel, JunctionMapGrampa) {
183   std::unique_ptr<GrampaMap> map(new GrampaMap());
184   run_test(map.get(), kGrampaPassCount);
185 }
186
187 } // namespace junction_test
188
189 int main(int argc, char** argv) {
190   // Init Google test
191   ::testing::InitGoogleTest(&argc, argv);
192   int result = RUN_ALL_TESTS();
193   return result;
194 }