Refactors Folly map test cases to use cdsstress library
[folly.git] / folly / stress-test / stress-parallel-folly-map.cpp
1 #include "map_test.h"
2
3 namespace folly_test {
4
5 class FollyMapInsDelFindTest_Parallel : public cds_test::stress_fixture {
6 protected:
7   static unsigned s_nInsertPercentage;
8   static unsigned s_nDeletePercentage;
9   static size_t s_nThreadCount;
10   static size_t s_nMapKeyRange;
11   static size_t s_nInitialMapSize;
12
13   enum actions { do_find, do_insert, do_delete };
14   static const unsigned int kShuffleSize = 100;
15   static actions s_arrShuffle[kShuffleSize];
16
17   static size_t s_nConcurrentHashMapPassCount;
18   static size_t s_nAtomicHashMapPassCount;
19   static size_t s_nAtomicUnorderedInsertMapPassCount;
20
21   static void InitShuffleArray() {
22     // Build an array of shuffled actions.
23     EXPECT_LE(s_nInsertPercentage + s_nDeletePercentage, 100);
24     actions* pFirst = s_arrShuffle;
25     actions* pLast = s_arrShuffle + s_nInsertPercentage;
26     std::fill(pFirst, pLast, do_insert);
27     pFirst = pLast;
28     pLast += s_nDeletePercentage;
29     std::fill(pFirst, pLast, do_delete);
30     pFirst = pLast;
31     pLast = s_arrShuffle + sizeof(s_arrShuffle) / sizeof(s_arrShuffle[0]);
32     if (pFirst < pLast) {
33       std::fill(pFirst, pLast, do_find);
34     }
35     std::random_device rd;
36     std::mt19937 g(rd());
37     std::shuffle(s_arrShuffle, pLast, g);
38   }
39
40   static void SetUpTestCase() {
41     InitShuffleArray();
42     const cds_test::config& cfg = get_config("ParallelFollyMap");
43     GetConfigNonZeroExpected(InsertPercentage, 5);
44     GetConfigNonZeroExpected(DeletePercentage, 5);
45     GetConfigNonZeroExpected(ThreadCount, 4);
46     GetConfigNonZeroExpected(MapKeyRange, 20000);
47     GetConfigNonZeroExpected(InitialMapSize, 20000);
48     GetConfigNonZeroExpected(ConcurrentHashMapPassCount, 1000);
49     GetConfigNonZeroExpected(AtomicHashMapPassCount, 1000);
50     GetConfigNonZeroExpected(AtomicUnorderedInsertMapPassCount, 1000);
51   }
52
53   template <typename Map>
54   static void run_test(Map* map, size_t pass_count, size_t* inserted_num,
55                        size_t* deleted_num) {
56     std::random_device rd;
57     std::mt19937 gen(rd());
58     std::uniform_int_distribution<size_t> dis(2, s_nMapKeyRange);
59
60     unsigned action_index = 0;
61     size_t nInsertedNum = 0;
62     size_t nDeletedNum = 0;
63     size_t nFindSuccess = 0;
64     size_t nOperations = 0;
65
66     for (size_t count = 0; count < pass_count; count++) {
67       // The number to operate on the map.
68       size_t key = dis(gen);
69       switch (s_arrShuffle[action_index]) {
70         case do_insert: {
71           size_t val = dis(gen);
72           if (map_insert(map, key, val)) {
73             nInsertedNum++;
74           }
75           break;
76         }
77         case do_delete: {
78           if (map_delete(map, key)) {
79             nDeletedNum++;
80           }
81           break;
82         }
83         case do_find: {
84           if (map_find(map, key)) {
85             ++nFindSuccess;
86           }
87           break;
88         }
89         default: { break; }
90       }
91       if (++action_index >= kShuffleSize) {
92         action_index = 0;
93       }
94     }
95     *inserted_num = nInsertedNum;
96     *deleted_num = nDeletedNum;
97   }
98 };
99
100 size_t FollyMapInsDelFindTest_Parallel::s_nThreadCount;
101 size_t FollyMapInsDelFindTest_Parallel::s_nMapKeyRange;
102 size_t FollyMapInsDelFindTest_Parallel::s_nInitialMapSize;
103 unsigned FollyMapInsDelFindTest_Parallel::s_nInsertPercentage;
104 unsigned FollyMapInsDelFindTest_Parallel::s_nDeletePercentage;
105 const unsigned int FollyMapInsDelFindTest_Parallel::kShuffleSize;
106 FollyMapInsDelFindTest_Parallel::actions FollyMapInsDelFindTest_Parallel::
107     s_arrShuffle[FollyMapInsDelFindTest_Parallel::kShuffleSize];
108 size_t FollyMapInsDelFindTest_Parallel::s_nConcurrentHashMapPassCount;
109 size_t FollyMapInsDelFindTest_Parallel::s_nAtomicHashMapPassCount;
110 size_t FollyMapInsDelFindTest_Parallel::s_nAtomicUnorderedInsertMapPassCount;
111
112 #define FollyMapThreading(map_type, pass_count)                                \
113   std::unique_ptr<std::thread[]> threads(new std::thread[s_nThreadCount]);     \
114   std::unique_ptr<size_t[]> inserted_nums(new size_t[s_nThreadCount]);         \
115   std::unique_ptr<size_t[]> deleted_nums(new size_t[s_nThreadCount]);          \
116   for (size_t i = 0; i < s_nThreadCount; i++) {                                \
117     threads[i] = std::thread(run_test<map_type>, map.get(), pass_count,        \
118                              &inserted_nums[i], &deleted_nums[i]);             \
119   }                                                                            \
120   size_t inserted_sum = 0;                                                     \
121   size_t deleted_sum = 0;                                                      \
122   for (size_t i = 0; i < s_nThreadCount; i++) {                                \
123     threads[i].join();                                                         \
124     inserted_sum += inserted_nums[i];                                          \
125     deleted_sum += deleted_nums[i];                                            \
126   }                                                                            \
127   EXPECT_LE(deleted_sum, inserted_sum);
128
129 TEST_F(FollyMapInsDelFindTest_Parallel, FollyConcurrentHashMap) {
130   std::unique_ptr<ConcurrentHashMap> map(
131       new ConcurrentHashMap(s_nInitialMapSize));
132   FollyMapThreading(ConcurrentHashMap, s_nConcurrentHashMapPassCount);
133 }
134
135 TEST_F(FollyMapInsDelFindTest_Parallel, FollyAtomicHashMap) {
136   std::unique_ptr<AtomicHashMap> map(
137       new AtomicHashMap(s_nInitialMapSize));
138   FollyMapThreading(AtomicHashMap, s_nAtomicHashMapPassCount);
139 }
140
141 TEST_F(FollyMapInsDelFindTest_Parallel, FollyAtomicUnorderedInsertMap) {
142   std::unique_ptr<AtomicUnorderedInsertMap> map(
143       new AtomicUnorderedInsertMap(s_nInitialMapSize));
144   FollyMapThreading(AtomicUnorderedInsertMap,
145      s_nAtomicUnorderedInsertMapPassCount);
146 }
147
148 } // namespace folly_test