Refactors folly sync test cases
[folly.git] / folly / stress-test / stress-sequential-folly-sync.cpp
1 #include "sync_test.h"
2
3 namespace folly_test {
4
5 class FollySyncTest_Sequential: public cds_test::stress_fixture {
6 protected:
7   // Simulate as the data protected by the lock.
8   static size_t locked_data;
9   static std::atomic<RcuData*> rcu_data;
10   // MicroLock
11   static size_t s_nMicroLockPassCount;
12   // MicroSpinLock
13   static size_t s_nMicroSpinLockPassCount;
14   // PicoSpinLock
15   static size_t s_nPicoSpinLockPassCount;
16   // SharedMutex
17   static size_t s_nSharedMutexPassCount;
18   // RWSpinLock
19   static size_t s_nRWSpinLockPassCount;
20   // RWTicketSpinLock
21   static size_t s_nRWTicketSpinLockPassCount;
22   // RCU
23   static size_t s_nRcuSyncPassCount;
24   static size_t s_nRcuNoSyncPassCount;
25   static size_t s_nRcuReaderOnlyPassCount;
26
27   static void SetUpTestCase() {
28     const cds_test::config& cfg = get_config("SequentialFollySync");
29     GetConfigNonZeroExpected(MicroLockPassCount, 2000000000);
30     GetConfigNonZeroExpected(MicroSpinLockPassCount, 1500000000);
31     GetConfigNonZeroExpected(PicoSpinLockPassCount, 2700000000);
32     GetConfigNonZeroExpected(SharedMutexPassCount, 5000000);
33     GetConfigNonZeroExpected(RWSpinLockPassCount, 5000000);
34     GetConfigNonZeroExpected(RWTicketSpinLockPassCount, 5000000);
35     GetConfigNonZeroExpected(RcuSyncPassCount, 180000);
36     GetConfigNonZeroExpected(RcuNoSyncPassCount, 3500000);
37     GetConfigNonZeroExpected(RcuReaderOnlyPassCount, 3000000);
38
39     // Initialize the RCU protected data.
40     rcu_data.store(new RcuData(), std::memory_order_relaxed);
41   }
42
43   static void run_rcu_reader_only(size_t pass_count) {
44     size_t sum = 1;
45     for (size_t count = 0; count < pass_count; count++) {
46       folly::rcu_reader g;
47       auto *data = rcu_data.load(std::memory_order_relaxed);
48       sum += (data->d1 + data->d2);
49     }
50     EXPECT_EQ(sum, 1);
51   }
52
53   static void run_rcu_sync(size_t pass_count) {
54     for (int write_percentage = 1; write_percentage <= 5; write_percentage += 1) {
55       size_t sum = 0;
56       for (size_t count = 0; count < pass_count; count++) {
57         for (int i = 0; i < 100; ++i) {
58           if (i < write_percentage) {
59             auto* old_data = rcu_data.load(std::memory_order_relaxed);
60             auto* new_data = new RcuData(*old_data);
61             new_data->d1++;
62             new_data->d2++;
63             rcu_data.store(new_data, std::memory_order_relaxed);
64             folly::synchronize_rcu();
65             delete old_data;
66           } else {
67             folly::rcu_reader g;
68             auto* data = rcu_data.load(std::memory_order_relaxed);
69             sum += (data->d1 + data->d2);
70           }
71         }
72       }
73       EXPECT_GT(sum, 0);
74     }
75   }
76
77   static void run_rcu_no_sync(size_t pass_count) {
78     for (int write_percentage = 1; write_percentage <= 5; write_percentage += 1) {
79       size_t sum = 0;
80       for (size_t count = 0; count < pass_count; count++) {
81         for (int i = 0; i < 100; ++i) {
82           if (i < write_percentage) {
83             auto* old_data = rcu_data.load(std::memory_order_relaxed);
84             auto* new_data = new RcuData(*old_data);
85             new_data->d1++;
86             new_data->d2++;
87             rcu_data.store(new_data, std::memory_order_relaxed);
88             folly::rcu_retire(old_data);
89           } else {
90             folly::rcu_reader g;
91             auto* data = rcu_data.load(std::memory_order_relaxed);
92             sum += (data->d1 + data->d2);
93           }
94         }
95       }
96       EXPECT_GT(sum, 0);
97     }
98   }
99
100   template <typename Lock>
101   static void run_rw_lock(size_t pass_count) {
102     std::unique_ptr<Lock> l(new Lock());
103     for (int write_percentage = 5; write_percentage < 20; write_percentage += 5) {
104       locked_data = 0;
105       size_t read_sum = 0;
106       size_t write_lock_cnt = 0;
107       for (size_t count = 0; count < pass_count; count++) {
108         for (int i = 0; i < 100; ++i) {
109           if (i < write_percentage) {
110             write_lock_cnt++;
111             l->lock();
112             locked_data++;
113             l->unlock();
114           } else {
115             l->lock_shared();
116             read_sum = locked_data;
117             l->unlock_shared();
118           }
119         }
120       }
121       EXPECT_EQ(write_lock_cnt, locked_data);
122       EXPECT_EQ(locked_data, read_sum);
123     }
124   }
125
126   template <typename Lock>
127   static void run_small_lock(size_t pass_count) {
128     std::unique_ptr<Lock> l(new Lock());
129     locked_data = 0;
130     l->init();
131     for (size_t count = 0; count < pass_count; count++) {
132       l->lock();
133       locked_data++;
134       l->unlock();
135     }
136     EXPECT_EQ(locked_data, pass_count);
137   }
138 };
139
140 size_t FollySyncTest_Sequential::locked_data;
141 std::atomic<RcuData*> FollySyncTest_Sequential::rcu_data;
142 size_t FollySyncTest_Sequential::s_nMicroLockPassCount;
143 size_t FollySyncTest_Sequential::s_nMicroSpinLockPassCount;
144 size_t FollySyncTest_Sequential::s_nPicoSpinLockPassCount;
145 size_t FollySyncTest_Sequential::s_nSharedMutexPassCount;
146 size_t FollySyncTest_Sequential::s_nRWSpinLockPassCount;
147 size_t FollySyncTest_Sequential::s_nRWTicketSpinLockPassCount;
148 size_t FollySyncTest_Sequential::s_nRcuSyncPassCount;
149 size_t FollySyncTest_Sequential::s_nRcuNoSyncPassCount;
150 size_t FollySyncTest_Sequential::s_nRcuReaderOnlyPassCount;
151
152 TEST_F(FollySyncTest_Sequential, FollyRCU_ReaderOnly) {
153   run_rcu_reader_only(s_nRcuReaderOnlyPassCount);
154 }
155
156 TEST_F(FollySyncTest_Sequential, FollyRCU_Sync) {
157   run_rcu_sync(s_nRcuSyncPassCount);
158 }
159
160 TEST_F(FollySyncTest_Sequential, FollyRCU_NoSync) {
161   run_rcu_no_sync(s_nRcuNoSyncPassCount);
162 }
163
164 TEST_F(FollySyncTest_Sequential, FollyMicroSpinLock) {
165   run_small_lock<MicroSpinLock>(s_nMicroSpinLockPassCount);
166 }
167
168 TEST_F(FollySyncTest_Sequential, FollyPicoSpinLock) {
169   run_small_lock<PicoSpinLock>(s_nPicoSpinLockPassCount);
170 }
171
172 TEST_F(FollySyncTest_Sequential, FollyMicroLock) {
173   run_small_lock<MicroLock>(s_nMicroLockPassCount);
174 }
175
176 TEST_F(FollySyncTest_Sequential, FollyRWTicketSpinLock_32) {
177   run_rw_lock<RWTicketSpinLock32>(s_nRWTicketSpinLockPassCount);
178 }
179
180 TEST_F(FollySyncTest_Sequential, FollyRWTicketSpinLock_64) {
181   run_rw_lock<RWTicketSpinLock64>(s_nRWTicketSpinLockPassCount);
182 }
183
184 TEST_F(FollySyncTest_Sequential, FollyRWSpinLock) {
185   run_rw_lock<RWSpinLock>(s_nRWSpinLockPassCount);
186 }
187
188 TEST_F(FollySyncTest_Sequential, FollySharedMutex_ReadPriority) {
189   run_rw_lock<SharedMutexReadPriority>(s_nSharedMutexPassCount);
190 }
191
192 TEST_F(FollySyncTest_Sequential, FollySharedMutex_WritePriority) {
193   run_rw_lock<SharedMutexWritePriority>(s_nSharedMutexPassCount);
194 }
195
196 } // namespace folly_test