proxygen
FlatCombiningTestHelpers.h
Go to the documentation of this file.
1 /*
2  * Copyright 2017-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
20 
21 #include <folly/Benchmark.h>
22 #include <glog/logging.h>
23 
24 #include <atomic>
25 #include <chrono>
26 #include <thread>
27 
28 namespace folly {
29 namespace test {
30 
31 void doWork(int work) {
32  uint64_t a = 0;
33  for (int i = work; i > 0; --i) {
34  a += i;
35  }
37 }
38 
39 template <
40  typename Example,
41  typename Req = bool,
42  typename Mutex = std::mutex,
43  template <typename> class Atom = std::atomic>
45  int nthreads,
46  int lines,
47  int numRecs,
48  int work,
49  int ops,
50  bool combining,
51  bool dedicated,
52  bool tc,
53  bool syncops,
54  bool excl = false,
55  bool allocAll = false) {
57  using Rec = typename FC::Rec;
58 
60 
61  std::atomic<bool> start{false};
62  std::atomic<int> started{0};
63  Example ex(lines, dedicated, numRecs);
64  std::atomic<uint64_t> total{0};
65  bool mutex = false;
66 
67  if (allocAll) {
68  std::vector<Rec*> v(numRecs);
69  for (int i = 0; i < numRecs; ++i) {
70  v[i] = ex.allocRec();
71  }
72  for (int i = numRecs; i > 0; --i) {
73  ex.freeRec(v[i - 1]);
74  }
75  }
76 
77  std::vector<std::thread> threads(nthreads);
78  for (int tid = 0; tid < nthreads; ++tid) {
79  threads[tid] = std::thread([&, tid] {
80  started.fetch_add(1);
81  Rec* myrec = (combining && tc) ? ex.allocRec() : nullptr;
82  uint64_t sum = 0;
83  while (!start.load()) {
84  ;
85  }
86 
87  if (!combining) {
88  // no combining
89  for (int i = tid; i < ops; i += nthreads) {
90  sum += ex.fetchAddNoFC(1);
91  doWork(work); // unrelated work
92  }
93  } else if (syncops) {
94  // sync combining
95  for (int i = tid; i < ops; i += nthreads) {
96  sum += ex.fetchAdd(1, myrec);
97  doWork(work); // unrelated work
98  }
99  } else {
100  // async combining
101  for (int i = tid; i < ops; i += nthreads) {
102  ex.add(1, myrec);
103  doWork(work); // unrelated work
104  }
105  }
106 
107  if (excl) {
108  // test of exclusive access through a lock holder
109  {
110  std::unique_lock<Mutex> l;
111  ex.holdLock(l);
112  CHECK(!mutex);
113  mutex = true;
114  VLOG(2) << tid << " " << ex.getVal() << " ...........";
115  using namespace std::chrono_literals;
116  /* sleep override */ // for coverage
117  std::this_thread::sleep_for(10ms);
118  VLOG(2) << tid << " " << ex.getVal() << " ===========";
119  CHECK(mutex);
120  mutex = false;
121  }
122  // test of explicit acquisition and release of exclusive access
123  ex.acquireExclusive();
124  {
125  CHECK(!mutex);
126  mutex = true;
127  VLOG(2) << tid << " " << ex.getVal() << " ...........";
128  using namespace std::chrono_literals;
129  /* sleep override */ // for coverage
130  std::this_thread::sleep_for(10ms);
131  VLOG(2) << tid << " " << ex.getVal() << " ===========";
132  CHECK(mutex);
133  mutex = false;
134  }
135  ex.releaseExclusive();
136  }
137 
138  total.fetch_add(sum);
139  if (combining && tc) {
140  ex.freeRec(myrec);
141  }
142  });
143  }
144 
145  while (started.load() < nthreads) {
146  ;
147  }
148  auto tbegin = std::chrono::steady_clock::now();
149 
150  // begin time measurement
151  susp.dismiss();
152  start.store(true);
153 
154  for (auto& t : threads) {
155  t.join();
156  }
157 
158  if (!syncops) {
159  // complete any pending asynch ops
160  ex.drainAll();
161  }
162 
163  // end time measurement
164  uint64_t duration = 0;
166  auto tend = std::chrono::steady_clock::now();
167  CHECK_EQ(ops, ex.getVal());
168  if (syncops) {
169  uint64_t n = (uint64_t)ops;
170  uint64_t expected = n * (n - 1) / 2;
171  CHECK_EQ(expected, total);
172  }
173  duration =
174  std::chrono::duration_cast<std::chrono::nanoseconds>(tend - tbegin)
175  .count();
176  }
177  return duration;
178 }
179 
181  int nthreads,
182  int lines,
183  int numRecs,
184  int work,
185  int ops,
186  bool combining,
187  bool simple,
188  bool dedicated,
189  bool tc,
190  bool syncops,
191  bool excl = false,
192  bool allocAll = false) {
193  using M = std::mutex;
194  if (simple) {
195  using Example = FcSimpleExample<M>;
196  return fc_test<Example, bool, M>(
197  nthreads,
198  lines,
199  numRecs,
200  work,
201  ops,
202  combining,
203  dedicated,
204  tc,
205  syncops,
206  excl,
207  allocAll);
208  } else {
209  using Example = FcCustomExample<Req, M>;
210  return fc_test<Example, Req, M>(
211  nthreads,
212  lines,
213  numRecs,
214  work,
215  ops,
216  combining,
217  dedicated,
218  tc,
219  syncops,
220  excl,
221  allocAll);
222  }
223 }
224 
225 } // namespace test
226 } // namespace folly
std::atomic< int64_t > sum(0)
auto v
uint64_t fc_test(int nthreads, int lines, int numRecs, int work, int ops, bool combining, bool dedicated, bool tc, bool syncops, bool excl=false, bool allocAll=false)
#define BENCHMARK_SUSPEND
Definition: Benchmark.h:576
uint64_t run_test(int nthreads, int lines, int numRecs, int work, int ops, bool combining, bool simple, bool dedicated, bool tc, bool syncops, bool excl=false, bool allocAll=false)
std::chrono::steady_clock::time_point now()
#define Mutex
static bool simple
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
static bool dedicated
std::vector< std::thread::id > threads
static int nthreads
#define Atom
static bool tc
char a
void doWork(int work)
const int ops
S lines(StringPiece source)
Definition: String.h:80
auto start
**Optimized Holders **The template hazptr_array< M > provides most of the functionality *of M hazptr_holder s but with faster construction destruction *for M
Definition: Hazptr.h:104
int * count
static bool syncops
std::mutex mutex
auto doNotOptimizeAway(const T &datum) -> typename std::enable_if< !detail::DoNotOptimizeAwayNeedsIndirect< T >::value >::type
Definition: Benchmark.h:258