Adds sync benchmarks
[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 = 3000000;
53 const size_t kRcuNoSyncPassCount = 2500000;
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 (size_t count = 0; count < pass_count; count++) {
69     RcuFoo* f = new RcuFoo();
70     folly::rcu_retire(f);
71     folly::synchronize_rcu();
72   }
73
74   auto finish_time = std::chrono::system_clock::now();
75   auto dur = finish_time - start_time;
76   auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
77   std::cout << "[       OK ] " << kTestName << "." << bench_name
78             << " (" << milisecs.count() << " ms)" << std::endl;
79 }
80
81 void run_rcu_no_sync(size_t pass_count, const char* bench_name) {
82   std::cout << "[ RUN      ] " << kTestName << "." << bench_name << std::endl;
83   auto start_time = std::chrono::system_clock::now();
84
85   for (int write_percentage = 5; write_percentage <= 10; write_percentage += 1) {
86     for (size_t count = 0; count < pass_count; count++) {
87       for (int i = 0; i < 100; ++i) {
88         if (i < write_percentage) {
89           RcuFoo* f = new RcuFoo();
90           folly::rcu_retire(f);
91         } else {
92           folly::rcu_reader g;
93         }
94       }
95     }
96   }
97
98   auto finish_time = std::chrono::system_clock::now();
99   auto dur = finish_time - start_time;
100   auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
101   std::cout << "[       OK ] " << kTestName << "." << bench_name
102             << " (" << milisecs.count() << " ms)" << std::endl;
103 }
104
105 template <typename Lock>
106 void run_rw_lock(size_t pass_count, const char* bench_name) {
107   std::cout << "[ RUN      ] " << kTestName << "." << bench_name << std::endl;
108   auto start_time = std::chrono::system_clock::now();
109
110   std::unique_ptr<Lock> l(new Lock());
111   for (int write_percentage = 5; write_percentage < 20; write_percentage += 5) {
112     for (size_t count = 0; count < pass_count; count++) {
113       for (int i = 0; i < 100; ++i) {
114         if (i < write_percentage) {
115           l->lock();
116           l->unlock();
117         } else {
118           l->lock_shared();
119           l->unlock_shared();
120         }
121       }
122     }
123   }
124
125   auto finish_time = std::chrono::system_clock::now();
126   auto dur = finish_time - start_time;
127   auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
128   std::cout << "[       OK ] " << kTestName << "." << bench_name
129             << " (" << milisecs.count() << " ms)" << std::endl;
130 }
131
132 template <typename Lock>
133 void run_small_lock(Lock* l, size_t pass_count, const char* bench_name) {
134     std::cout << "[ RUN      ] " << kTestName << "." << bench_name << std::endl;
135     auto start_time = std::chrono::system_clock::now();
136
137     for (size_t count = 0; count < pass_count; count++) {
138       l->lock();
139       l->unlock();
140     }
141     auto finish_time = std::chrono::system_clock::now();
142     auto dur = finish_time - start_time;
143     auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
144     std::cout << "[       OK ] " << kTestName << "." << bench_name
145               << " (" << milisecs.count() << " ms)" << std::endl;
146 }
147
148 template <typename Lock>
149 void init_run_lock(size_t pass_count, const char* bench_name) {
150   std::unique_ptr<Lock> l(new Lock());
151   l->init();
152   run_small_lock<Lock>(l.get(), pass_count, bench_name);
153 }
154
155 int main() {
156   run_rcu_sync(kRcuSyncPassCount, kRcuSyncBenchmarkName);
157   run_rcu_no_sync(kRcuNoSyncPassCount, kRcuNoSyncBenchmarkName);
158
159   run_rw_lock<RWTicketSpinLock32>(kRWTicketSpinLockPassCount,
160                                   kRWTicketSpinLock32BenchmarkName);
161   run_rw_lock<RWTicketSpinLock64>(kRWTicketSpinLockPassCount,
162                                   kRWTicketSpinLock64BenchmarkName);
163
164   run_rw_lock<RWSpinLock>(kRWSpinLockPassCount, kRWSpinLockBenchmarkName);
165
166   run_rw_lock<SharedMutexReadPriority>(
167       kSharedMutexPassCount, kSharedMutexReadPriorityBenchmarkName);
168   run_rw_lock<SharedMutexWritePriority>(
169       kSharedMutexPassCount, kSharedMutexWritePriorityBenchmarkName);
170
171   init_run_lock<MicroSpinLock>(kMicroSpinLockPassCount,
172                                kMicroSpinLockBenchmarkName);
173   init_run_lock<PicoSpinLock>(kPicoSpinLockPassCount,
174                               kPicoSpinLockBenchmarkName);
175   init_run_lock<MicroLock>(kMicroLockPassCount, kMicroLockBenchmarkName);
176   return 0;
177 }