Refactors RCU test cases
[folly.git] / folly / stress-test / stress-sequential-folly-sync.cpp
1 #include <folly/SmallLocks.h>
2 #include <folly/RWSpinLock.h>
3 #include <folly/SharedMutex.h>
4 #include <folly/synchronization/Rcu.h>
5
6 #include <chrono>
7 #include <cassert>
8 #include <iostream>
9 #include <memory>
10
11 namespace {
12
13 const char* kTestName = "LockUnlock";
14
15 // MicroLock
16 const size_t kMicroLockPassCount = 2000000000;
17 const char* kMicroLockBenchmarkName = "FollyMicroLock";
18 typedef folly::MicroLock MicroLock;
19
20 // MicroSpinLock
21 const size_t kMicroSpinLockPassCount = 1500000000;
22 const char* kMicroSpinLockBenchmarkName = "FollyMicroSpinLock";
23 typedef folly::MicroSpinLock MicroSpinLock;
24
25 // PicoSpinLock
26 const size_t kPicoSpinLockPassCount = 2700000000;
27 const char* kPicoSpinLockBenchmarkName = "FollyPicoSpinLock";
28 typedef folly::PicoSpinLock<size_t> PicoSpinLock;
29
30 // SharedMutex
31 const size_t kSharedMutexPassCount = 5000000;
32 const char* kSharedMutexReadPriorityBenchmarkName =
33     "FollySharedMutex_ReadPriority";
34 const char* kSharedMutexWritePriorityBenchmarkName =
35     "FollySharedMutex_WritePriority";
36 typedef folly::SharedMutexReadPriority SharedMutexReadPriority;
37 typedef folly::SharedMutexWritePriority SharedMutexWritePriority;
38
39 // RWSpinLock
40 const size_t kRWSpinLockPassCount = 5000000;
41 const char* kRWSpinLockBenchmarkName = "FollyRWSpinLock";
42 typedef folly::RWSpinLock RWSpinLock;
43
44 // RWTicketSpinLock
45 const size_t kRWTicketSpinLockPassCount = 5000000;
46 const char* kRWTicketSpinLock32BenchmarkName = "FollyRWTicketSpinLock_32";
47 const char* kRWTicketSpinLock64BenchmarkName = "FollyRWTicketSpinLock_64";
48 typedef folly::RWTicketSpinLock32 RWTicketSpinLock32;
49 typedef folly::RWTicketSpinLock64 RWTicketSpinLock64;
50
51 // RCU
52 const size_t kRcuSyncPassCount = 180000;
53 const size_t kRcuNoSyncPassCount = 3500000;
54 const char* kRcuSyncBenchmarkName = "FollyRCU_Sync";
55 const char* kRcuNoSyncBenchmarkName = "FollyRCU_NoSync";
56 // Represent the RCU-protected data.
57 struct RcuFoo {
58   size_t f1;
59   size_t f2;
60 };
61
62 }
63
64 void run_rcu_sync(size_t pass_count, const char* bench_name) {
65   std::cout << "[ RUN      ] " << kTestName << "." << bench_name << std::endl;
66   auto start_time = std::chrono::system_clock::now();
67
68   for (int write_percentage = 1; write_percentage <= 5; write_percentage += 1) {
69     for (size_t count = 0; count < pass_count; count++) {
70       for (int i = 0; i < 100; ++i) {
71         if (i < write_percentage) {
72           RcuFoo* f = new RcuFoo();
73           folly::rcu_retire(f);
74           folly::synchronize_rcu();
75         } else {
76           folly::rcu_reader g;
77         }
78       }
79     }
80   }
81
82   auto finish_time = std::chrono::system_clock::now();
83   auto dur = finish_time - start_time;
84   auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
85   std::cout << "[       OK ] " << kTestName << "." << bench_name
86             << " (" << milisecs.count() << " ms)" << std::endl;
87 }
88
89 void run_rcu_no_sync(size_t pass_count, const char* bench_name) {
90   std::cout << "[ RUN      ] " << kTestName << "." << bench_name << std::endl;
91   auto start_time = std::chrono::system_clock::now();
92
93   for (int write_percentage = 1; write_percentage <= 5; write_percentage += 1) {
94     for (size_t count = 0; count < pass_count; count++) {
95       for (int i = 0; i < 100; ++i) {
96         if (i < write_percentage) {
97           RcuFoo* f = new RcuFoo();
98           folly::rcu_retire(f);
99         } else {
100           folly::rcu_reader g;
101         }
102       }
103     }
104   }
105
106   auto finish_time = std::chrono::system_clock::now();
107   auto dur = finish_time - start_time;
108   auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
109   std::cout << "[       OK ] " << kTestName << "." << bench_name
110             << " (" << milisecs.count() << " ms)" << std::endl;
111 }
112
113 template <typename Lock>
114 void run_rw_lock(size_t pass_count, const char* bench_name) {
115   std::cout << "[ RUN      ] " << kTestName << "." << bench_name << std::endl;
116   auto start_time = std::chrono::system_clock::now();
117
118   std::unique_ptr<Lock> l(new Lock());
119   for (int write_percentage = 5; write_percentage < 20; write_percentage += 5) {
120     for (size_t count = 0; count < pass_count; count++) {
121       for (int i = 0; i < 100; ++i) {
122         if (i < write_percentage) {
123           l->lock();
124           l->unlock();
125         } else {
126           l->lock_shared();
127           l->unlock_shared();
128         }
129       }
130     }
131   }
132
133   auto finish_time = std::chrono::system_clock::now();
134   auto dur = finish_time - start_time;
135   auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
136   std::cout << "[       OK ] " << kTestName << "." << bench_name
137             << " (" << milisecs.count() << " ms)" << std::endl;
138 }
139
140 template <typename Lock>
141 void run_small_lock(Lock* l, size_t pass_count, const char* bench_name) {
142     std::cout << "[ RUN      ] " << kTestName << "." << bench_name << std::endl;
143     auto start_time = std::chrono::system_clock::now();
144
145     for (size_t count = 0; count < pass_count; count++) {
146       l->lock();
147       l->unlock();
148     }
149     auto finish_time = std::chrono::system_clock::now();
150     auto dur = finish_time - start_time;
151     auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
152     std::cout << "[       OK ] " << kTestName << "." << bench_name
153               << " (" << milisecs.count() << " ms)" << std::endl;
154 }
155
156 template <typename Lock>
157 void init_run_lock(size_t pass_count, const char* bench_name) {
158   std::unique_ptr<Lock> l(new Lock());
159   l->init();
160   run_small_lock<Lock>(l.get(), pass_count, bench_name);
161 }
162
163 int main() {
164   run_rcu_sync(kRcuSyncPassCount, kRcuSyncBenchmarkName);
165   run_rcu_no_sync(kRcuNoSyncPassCount, kRcuNoSyncBenchmarkName);
166
167   run_rw_lock<RWTicketSpinLock32>(kRWTicketSpinLockPassCount,
168                                   kRWTicketSpinLock32BenchmarkName);
169   run_rw_lock<RWTicketSpinLock64>(kRWTicketSpinLockPassCount,
170                                   kRWTicketSpinLock64BenchmarkName);
171
172   run_rw_lock<RWSpinLock>(kRWSpinLockPassCount, kRWSpinLockBenchmarkName);
173
174   run_rw_lock<SharedMutexReadPriority>(
175       kSharedMutexPassCount, kSharedMutexReadPriorityBenchmarkName);
176   run_rw_lock<SharedMutexWritePriority>(
177       kSharedMutexPassCount, kSharedMutexWritePriorityBenchmarkName);
178
179   init_run_lock<MicroSpinLock>(kMicroSpinLockPassCount,
180                                kMicroSpinLockBenchmarkName);
181   init_run_lock<PicoSpinLock>(kPicoSpinLockPassCount,
182                               kPicoSpinLockBenchmarkName);
183   init_run_lock<MicroLock>(kMicroLockPassCount, kMicroLockBenchmarkName);
184   return 0;
185 }