proxygen
DynamicBoundedQueueTest.cpp File Reference
#include <folly/concurrency/DynamicBoundedQueue.h>
#include <folly/MPMCQueue.h>
#include <folly/ProducerConsumerQueue.h>
#include <folly/portability/GTest.h>
#include <glog/logging.h>
#include <atomic>
#include <thread>

Go to the source code of this file.

Classes

class  MPMC< T >
 
class  PCQ< T >
 
struct  IntArray< M >
 

Typedefs

template<typename T , bool MayBlock, typename WeightFn >
using DSPSC = folly::DSPSCQueue< T, MayBlock, 8, 7, WeightFn >
 
template<typename T , bool MayBlock, typename WeightFn >
using DMPSC = folly::DMPSCQueue< T, MayBlock, 8, 7, WeightFn >
 
template<typename T , bool MayBlock, typename WeightFn >
using DSPMC = folly::DSPMCQueue< T, MayBlock, 8, 7, WeightFn >
 
template<typename T , bool MayBlock, typename WeightFn >
using DMPMC = folly::DMPMCQueue< T, MayBlock, 8, 7, WeightFn >
 
template<typename T , bool , typename >
using FMPMC = MPMC< T >
 
template<typename T , bool , typename >
using FPCQ = PCQ< T >
 

Functions

 DEFINE_bool (bench, false,"run benchmark")
 
 DEFINE_int32 (reps, 10,"number of reps")
 
 DEFINE_int32 (ops, 1000000,"number of operations per rep")
 
 DEFINE_int64 (capacity, 1000000,"capacity")
 
template<template< typename, bool, typename > class Q, bool MayBlock>
void basic_test ()
 
 TEST (DynamicBoundedQueue, basic)
 
template<template< typename, bool, typename > class Q, bool MayBlock>
void move_test ()
 
 TEST (DynamicBoundedQueue, move)
 
template<template< typename, bool, typename > class Q, bool MayBlock>
void capacity_test ()
 
 TEST (DynamicBoundedQueue, capacity)
 
template<typename ProdFunc , typename ConsFunc , typename EndFunc >
uint64_t run_once (int nprod, int ncons, const ProdFunc &prodFn, const ConsFunc &consFn, const EndFunc &endFn)
 
template<bool SingleProducer, bool SingleConsumer, bool MayBlock>
void enq_deq_test (const int nprod, const int ncons)
 
 TEST (DynamicBoundedQueue, enq_deq)
 
template<typename RepFunc >
uint64_t runBench (const std::string &name, int ops, const RepFunc &repFn)
 
template<template< typename, bool, typename > class Q, typename T , int Op>
uint64_t bench (const int nprod, const int ncons, const std::string &name)
 
void dottedLine ()
 
template<typename T >
void type_benches (const int np, const int nc, const std::string &name)
 
void benches (const int np, const int nc)
 
 TEST (DynamicBoundedQueue, bench)
 

Typedef Documentation

template<typename T , bool MayBlock, typename WeightFn >
using DMPMC = folly::DMPMCQueue<T, MayBlock, 8, 7, WeightFn>

Definition at line 42 of file DynamicBoundedQueueTest.cpp.

template<typename T , bool MayBlock, typename WeightFn >
using DMPSC = folly::DMPSCQueue<T, MayBlock, 8, 7, WeightFn>

Definition at line 36 of file DynamicBoundedQueueTest.cpp.

template<typename T , bool MayBlock, typename WeightFn >
using DSPMC = folly::DSPMCQueue<T, MayBlock, 8, 7, WeightFn>

Definition at line 39 of file DynamicBoundedQueueTest.cpp.

template<typename T , bool MayBlock, typename WeightFn >
using DSPSC = folly::DSPSCQueue<T, MayBlock, 8, 7, WeightFn>

Definition at line 33 of file DynamicBoundedQueueTest.cpp.

template<typename T , bool , typename >
using FMPMC = MPMC<T>

Definition at line 474 of file DynamicBoundedQueueTest.cpp.

template<typename T , bool , typename >
using FPCQ = PCQ<T>

Definition at line 515 of file DynamicBoundedQueueTest.cpp.

Function Documentation

template<template< typename, bool, typename > class Q, bool MayBlock>
void basic_test ( )

Definition at line 45 of file DynamicBoundedQueueTest.cpp.

References ASSERT_EQ, ASSERT_FALSE, ASSERT_TRUE, now(), uint64_t, v, and val.

45  {
46  auto dur = std::chrono::microseconds(100);
47  auto deadline = std::chrono::steady_clock::now() + dur;
48 
49  struct CustomWeightFn {
50  uint64_t operator()(int val) {
51  return val * 100;
52  }
53  };
54 
55  Q<int, MayBlock, CustomWeightFn> q(10000);
56 
57  ASSERT_TRUE(q.empty());
58  ASSERT_EQ(q.size(), 0);
59  int v;
60  ASSERT_FALSE(q.try_dequeue(v));
61 
62  q.enqueue(1);
63  ASSERT_TRUE(q.try_enqueue(2));
64  ASSERT_TRUE(q.try_enqueue_until(3, deadline));
65  ASSERT_TRUE(q.try_enqueue_for(4, dur));
66 
67  ASSERT_EQ(q.size(), 4);
68  ASSERT_EQ(q.weight(), 1000);
69  ASSERT_FALSE(q.empty());
70 
71  q.dequeue(v);
72  ASSERT_EQ(v, 1);
73  ASSERT_TRUE(q.try_dequeue(v));
74  ASSERT_EQ(v, 2);
75  ASSERT_TRUE(q.try_dequeue_until(v, deadline));
76  ASSERT_EQ(v, 3);
77  ASSERT_TRUE(q.try_dequeue_for(v, dur));
78  ASSERT_EQ(v, 4);
79 
80  ASSERT_TRUE(q.empty());
81  ASSERT_EQ(q.size(), 0);
82  ASSERT_EQ(q.weight(), 0);
83 }
auto v
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
std::chrono::steady_clock::time_point now()
double val
Definition: String.cpp:273
#define ASSERT_FALSE(condition)
Definition: gtest.h:1868
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
template<template< typename, bool, typename > class Q, typename T , int Op>
uint64_t bench ( const int  nprod,
const int  ncons,
const std::string name 
)

Definition at line 372 of file DynamicBoundedQueueTest.cpp.

References ASSERT_EQ, i, ops, run_once(), runBench(), sum(), T, uint64_t, and v.

372  {
373  int ops = FLAGS_ops;
374  auto repFn = [&] {
375  Q<T, Op == 3 || Op == 4 || Op == 5, folly::DefaultWeightFn<T>> q(
376  FLAGS_capacity);
377  std::atomic<uint64_t> sum(0);
378  auto prod = [&](int tid) {
379  for (int i = tid; i < ops; i += nprod) {
380  if (Op == 0 || Op == 3) {
381  while (!q.try_enqueue(i)) {
382  /* keep trying */;
383  }
384  } else if (Op == 1 || Op == 4) {
385  while (!q.try_enqueue_for(i, std::chrono::microseconds(1000))) {
386  /* keep trying */;
387  }
388  } else {
389  q.enqueue(i);
390  }
391  }
392  };
393  auto cons = [&](int tid) {
394  uint64_t mysum = 0;
395  T v = -1;
396  for (int i = tid; i < ops; i += ncons) {
397  if (Op == 0 || Op == 3) {
398  while (!q.try_dequeue(v)) {
399  /* keep trying */;
400  }
401  } else if (Op == 1 || Op == 4) {
402  while (!q.try_dequeue_for(v, std::chrono::microseconds(1000))) {
403  /* keep trying */;
404  }
405  } else {
406  q.dequeue(v);
407  }
408  if (nprod == 1 && ncons == 1) {
409  DCHECK_EQ(int(v), i);
410  }
411  mysum += v;
412  }
413  sum.fetch_add(mysum);
414  };
415  auto endfn = [&] {
416  uint64_t expected = ops;
417  expected *= ops - 1;
418  expected /= 2;
419  ASSERT_EQ(sum.load(), expected);
420  };
421  return run_once(nprod, ncons, prod, cons, endfn);
422  };
423  return runBench(name, ops, repFn);
424 }
#define T(v)
Definition: http_parser.c:233
std::atomic< int64_t > sum(0)
auto v
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
uint64_t run_once(int nprod, int ncons, const ProdFunc &prodFn, const ConsFunc &consFn, const EndFunc &endFn)
uint64_t runBench(const std::string &name, int ops, const RepFunc &repFn)
const char * name
Definition: http_parser.c:437
const int ops
void benches ( const int  np,
const int  nc 
)

Definition at line 585 of file DynamicBoundedQueueTest.cpp.

Referenced by TEST().

585  {
586  std::cout << "====================== " << std::setw(2) << np << " prod"
587  << " " << std::setw(2) << nc << " cons"
588  << " ======================" << std::endl;
589  type_benches<uint32_t>(np, nc, "=== uint32_t ======");
590  // Benchmarks for other element sizes can be added as follows:
591  // type_benches<IntArray<4>>(np, nc, "=== IntArray<4> ===");
592 }
template<template< typename, bool, typename > class Q, bool MayBlock>
void capacity_test ( )

Definition at line 142 of file DynamicBoundedQueueTest.cpp.

References ASSERT_EQ, ASSERT_FALSE, ASSERT_TRUE, uint64_t, v, and val.

142  {
143  struct CustomWeightFn {
144  uint64_t operator()(int val) {
145  return val;
146  }
147  };
148 
149  Q<int, MayBlock, CustomWeightFn> q(1000);
150  ASSERT_EQ(q.weight(), 0);
151  int v;
152  q.enqueue(100);
153  ASSERT_EQ(q.weight(), 100);
154  q.enqueue(300);
155  ASSERT_EQ(q.weight(), 400);
156  ASSERT_FALSE(q.try_enqueue(1200));
157  q.reset_capacity(2000); // reset capacityy to 2000
158  ASSERT_TRUE(q.try_enqueue(1200));
159  ASSERT_EQ(q.weight(), 1600);
160  ASSERT_EQ(q.size(), 3);
161  q.reset_capacity(1000); // reset capacity back to 1000
162  ASSERT_FALSE(q.try_enqueue(100));
163  q.dequeue(v);
164  ASSERT_EQ(v, 100);
165  ASSERT_EQ(q.weight(), 1500);
166  q.dequeue(v);
167  ASSERT_EQ(v, 300);
168  ASSERT_EQ(q.weight(), 1200);
169 }
auto v
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
double val
Definition: String.cpp:273
#define ASSERT_FALSE(condition)
Definition: gtest.h:1868
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
DEFINE_bool ( bench  ,
false  ,
"run benchmark  
)
DEFINE_int32 ( reps  ,
10  ,
"number of reps"   
)
DEFINE_int32 ( ops  ,
1000000  ,
"number of operations per rep"   
)
DEFINE_int64 ( capacity  ,
1000000  ,
"capacity"   
)
void dottedLine ( )

Definition at line 531 of file DynamicBoundedQueueTest.cpp.

Referenced by TEST(), and type_benches().

531  {
532  std::cout << ".............................................................."
533  << std::endl;
534 }
template<bool SingleProducer, bool SingleConsumer, bool MayBlock>
void enq_deq_test ( const int  nprod,
const int  ncons 
)

Definition at line 241 of file DynamicBoundedQueueTest.cpp.

References ASSERT_EQ, folly::DynamicBoundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, WeightFn, Atom >::dequeue(), folly::DynamicBoundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, WeightFn, Atom >::enqueue(), i, ops, run_once(), sum(), folly::DynamicBoundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, WeightFn, Atom >::try_dequeue(), folly::DynamicBoundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, WeightFn, Atom >::try_dequeue_for(), folly::DynamicBoundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, WeightFn, Atom >::try_enqueue(), folly::DynamicBoundedQueue< T, SingleProducer, SingleConsumer, MayBlock, LgSegmentSize, LgAlign, WeightFn, Atom >::try_enqueue_for(), uint64_t, and v.

241  {
242  if (SingleProducer) {
243  ASSERT_EQ(nprod, 1);
244  }
245  if (SingleConsumer) {
246  ASSERT_EQ(ncons, 1);
247  }
248 
249  int ops = 1000;
251  q(10);
252  std::atomic<uint64_t> sum(0);
253 
254  auto prod = [&](int tid) {
255  for (int i = tid; i < ops; i += nprod) {
256  if ((i % 3) == 0) {
257  while (!q.try_enqueue(i)) {
258  /* keep trying */;
259  }
260  } else if ((i % 3) == 1) {
261  auto dur = std::chrono::microseconds(100);
262  while (!q.try_enqueue_for(i, dur)) {
263  /* keep trying */;
264  }
265  } else {
266  q.enqueue(i);
267  }
268  }
269  };
270 
271  auto cons = [&](int tid) {
272  uint64_t mysum = 0;
273  for (int i = tid; i < ops; i += ncons) {
274  int v;
275  if ((i % 3) == 0) {
276  while (!q.try_dequeue(v)) {
277  /* keep trying */;
278  }
279  } else if ((i % 3) == 1) {
280  auto dur = std::chrono::microseconds(100);
281  while (!q.try_dequeue_for(v, dur)) {
282  /* keep trying */;
283  }
284  } else {
285  q.dequeue(v);
286  }
287  if (nprod == 1 && ncons == 1) {
288  ASSERT_EQ(v, i);
289  }
290  mysum += v;
291  }
292  sum.fetch_add(mysum);
293  };
294 
295  auto endfn = [&] {
296  uint64_t expected = ops;
297  expected *= ops - 1;
298  expected /= 2;
299  ASSERT_EQ(sum.load(), expected);
300  };
301  run_once(nprod, ncons, prod, cons, endfn);
302 }
std::atomic< int64_t > sum(0)
auto v
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
uint64_t run_once(int nprod, int ncons, const ProdFunc &prodFn, const ConsFunc &consFn, const EndFunc &endFn)
const int ops
template<template< typename, bool, typename > class Q, bool MayBlock>
void move_test ( )

Definition at line 97 of file DynamicBoundedQueueTest.cpp.

References ASSERT_EQ, ASSERT_TRUE, folly::gen::move, folly::pushmi::__adl::noexcept(), now(), uint64_t, and v.

97  {
98  struct Foo {
99  int v_;
100  explicit Foo(int v) noexcept : v_(v) {}
101  Foo(const Foo&) = delete;
102  Foo& operator=(const Foo&) = delete;
103  Foo(Foo&& other) noexcept : v_(other.v_) {}
104  Foo& operator=(Foo&& other) noexcept {
105  v_ = other.v_;
106  return *this;
107  }
108  };
109 
110  struct CustomWeightFn {
111  uint64_t operator()(Foo&&) {
112  return 10;
113  }
114  };
115 
116  auto dur = std::chrono::microseconds(100);
117  auto deadline = std::chrono::steady_clock::now() + dur;
118 
119  Q<Foo, MayBlock, CustomWeightFn> q(100);
120  Foo v(1);
121  q.enqueue(std::move(v));
122  ASSERT_TRUE(q.try_enqueue(std::move(v)));
123  ASSERT_TRUE(q.try_enqueue_until(std::move(v), deadline));
124  ASSERT_TRUE(q.try_enqueue_for(std::move(v), dur));
125 
126  ASSERT_EQ(q.size(), 4);
127  ASSERT_EQ(q.weight(), 40);
128 }
auto v
Foo(std::atomic< int > &d)
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::chrono::steady_clock::time_point now()
requires E e noexcept(noexcept(s.error(std::move(e))))
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
template<typename ProdFunc , typename ConsFunc , typename EndFunc >
uint64_t run_once ( int  nprod,
int  ncons,
const ProdFunc &  prodFn,
const ConsFunc &  consFn,
const EndFunc &  endFn 
)
inline

Definition at line 183 of file DynamicBoundedQueueTest.cpp.

References count, i, now(), and start.

Referenced by bench(), and enq_deq_test().

188  {
189  std::atomic<bool> start{false};
190  std::atomic<int> ready{0};
191 
192  /* producers */
193  std::vector<std::thread> prodThr(nprod);
194  for (int tid = 0; tid < nprod; ++tid) {
195  prodThr[tid] = std::thread([&, tid] {
196  ++ready;
197  while (!start.load()) {
198  /* spin */;
199  }
200  prodFn(tid);
201  });
202  }
203 
204  /* consumers */
205  std::vector<std::thread> consThr(ncons);
206  for (int tid = 0; tid < ncons; ++tid) {
207  consThr[tid] = std::thread([&, tid] {
208  ++ready;
209  while (!start.load()) {
210  /* spin */;
211  }
212  consFn(tid);
213  });
214  }
215 
216  /* wait for all producers and consumers to be ready */
217  while (ready.load() < (nprod + ncons)) {
218  /* spin */;
219  }
220 
221  /* begin time measurement */
222  auto tbegin = std::chrono::steady_clock::now();
223  start.store(true);
224 
225  /* wait for completion */
226  for (int i = 0; i < nprod; ++i) {
227  prodThr[i].join();
228  }
229  for (int i = 0; i < ncons; ++i) {
230  consThr[i].join();
231  }
232 
233  /* end time measurement */
234  auto tend = std::chrono::steady_clock::now();
235  endFn();
236  return std::chrono::duration_cast<std::chrono::nanoseconds>(tend - tbegin)
237  .count();
238 }
std::chrono::steady_clock::time_point now()
auto start
int * count
template<typename RepFunc >
uint64_t runBench ( const std::string name,
int  ops,
const RepFunc &  repFn 
)

Definition at line 340 of file DynamicBoundedQueueTest.cpp.

References max, min, name, string, sum(), T, uint64_t, and folly::unit.

Referenced by bench().

340  {
341  int reps = FLAGS_reps;
342  uint64_t min = UINTMAX_MAX;
343  uint64_t max = 0;
344  uint64_t sum = 0;
345 
346  repFn(); // sometimes first run is outlier
347  for (int r = 0; r < reps; ++r) {
348  uint64_t dur = repFn();
349  sum += dur;
350  min = std::min(min, dur);
351  max = std::max(max, dur);
352  // if each rep takes too long run at least 2 reps
353  const uint64_t minute = 60000000000ULL;
354  if (sum > minute && r >= 1) {
355  reps = r + 1;
356  break;
357  }
358  }
359 
360  const std::string unit = " ns";
361  uint64_t avg = sum / reps;
362  uint64_t res = min;
363  std::cout << name;
364  std::cout << " " << std::setw(4) << max / ops << unit;
365  std::cout << " " << std::setw(4) << avg / ops << unit;
366  std::cout << " " << std::setw(4) << res / ops << unit;
367  std::cout << std::endl;
368  return res;
369 }
std::atomic< int64_t > sum(0)
LogLevel max
Definition: LogLevel.cpp:31
const char * name
Definition: http_parser.c:437
LogLevel min
Definition: LogLevel.cpp:30
constexpr Unit unit
Definition: Unit.h:45
const int ops
const char * string
Definition: Conv.cpp:212
TEST ( DynamicBoundedQueue  ,
basic   
)

Definition at line 85 of file DynamicBoundedQueueTest.cpp.

85  {
86  basic_test<DSPSC, false>();
87  basic_test<DMPSC, false>();
88  basic_test<DSPMC, false>();
89  basic_test<DMPMC, false>();
90  basic_test<DSPSC, true>();
91  basic_test<DMPSC, true>();
92  basic_test<DSPMC, true>();
93  basic_test<DMPMC, true>();
94 }
TEST ( DynamicBoundedQueue  ,
move   
)

Definition at line 130 of file DynamicBoundedQueueTest.cpp.

130  {
131  move_test<DSPSC, false>();
132  move_test<DMPSC, false>();
133  move_test<DSPMC, false>();
134  move_test<DMPMC, false>();
135  move_test<DSPSC, true>();
136  move_test<DMPSC, true>();
137  move_test<DSPMC, true>();
138  move_test<DMPMC, true>();
139 }
TEST ( DynamicBoundedQueue  ,
capacity   
)

Definition at line 171 of file DynamicBoundedQueueTest.cpp.

171  {
172  capacity_test<DSPSC, false>();
173  capacity_test<DMPSC, false>();
174  capacity_test<DSPMC, false>();
175  capacity_test<DMPMC, false>();
176  capacity_test<DSPSC, true>();
177  capacity_test<DMPSC, true>();
178  capacity_test<DSPMC, true>();
179  capacity_test<DMPMC, true>();
180 }
TEST ( DynamicBoundedQueue  ,
enq_deq   
)

Definition at line 304 of file DynamicBoundedQueueTest.cpp.

304  {
305  /* SPSC */
306  enq_deq_test<true, true, false>(1, 1);
307  enq_deq_test<true, true, true>(1, 1);
308  /* MPSC */
309  enq_deq_test<false, true, false>(1, 1);
310  enq_deq_test<false, true, true>(1, 1);
311  enq_deq_test<false, true, false>(2, 1);
312  enq_deq_test<false, true, true>(2, 1);
313  enq_deq_test<false, true, false>(10, 1);
314  enq_deq_test<false, true, true>(10, 1);
315  /* SPMC */
316  enq_deq_test<true, false, false>(1, 1);
317  enq_deq_test<true, false, true>(1, 1);
318  enq_deq_test<true, false, false>(1, 2);
319  enq_deq_test<true, false, true>(1, 2);
320  enq_deq_test<true, false, false>(1, 10);
321  enq_deq_test<true, false, true>(1, 10);
322  /* MPMC */
323  enq_deq_test<false, false, false>(1, 1);
324  enq_deq_test<false, false, true>(1, 1);
325  enq_deq_test<false, false, false>(2, 1);
326  enq_deq_test<false, false, true>(2, 1);
327  enq_deq_test<false, false, false>(10, 1);
328  enq_deq_test<false, false, true>(10, 1);
329  enq_deq_test<false, false, false>(1, 2);
330  enq_deq_test<false, false, true>(1, 2);
331  enq_deq_test<false, false, false>(1, 10);
332  enq_deq_test<false, false, true>(1, 10);
333  enq_deq_test<false, false, false>(2, 2);
334  enq_deq_test<false, false, true>(2, 2);
335  enq_deq_test<false, false, false>(10, 10);
336  enq_deq_test<false, false, true>(10, 10);
337 }
TEST ( DynamicBoundedQueue  ,
bench   
)

Definition at line 594 of file DynamicBoundedQueueTest.cpp.

References benches(), and dottedLine().

594  {
595  if (!FLAGS_bench) {
596  return;
597  }
598  std::cout << "=============================================================="
599  << std::endl;
600  std::cout << std::setw(2) << FLAGS_reps << " reps of " << std::setw(8)
601  << FLAGS_ops << " handoffs\n";
602  dottedLine();
603  std::cout << "Using capacity " << FLAGS_capacity << " for all queues\n";
604  std::cout << "=============================================================="
605  << std::endl;
606  std::cout << "Test name Max time Avg time Min time"
607  << std::endl;
608 
609  for (int np : {1, 8, 32}) {
610  for (int nc : {1, 8, 32}) {
611  benches(np, nc);
612  }
613  }
614 }
void dottedLine()
void benches(const int np, const int nc)
template<typename T >
void type_benches ( const int  np,
const int  nc,
const std::string name 
)

Definition at line 537 of file DynamicBoundedQueueTest.cpp.

References dottedLine().

537  {
538  std::cout << name
539  << "===========================================" << std::endl;
540  if (np == 1 && nc == 1) {
541  bench<DSPSC, T, 0>(1, 1, "DSPSC try spin only ");
542  bench<DSPSC, T, 1>(1, 1, "DSPSC timed spin only ");
543  bench<DSPSC, T, 2>(1, 1, "DSPSC wait spin only ");
544  bench<DSPSC, T, 3>(1, 1, "DSPSC try may block ");
545  bench<DSPSC, T, 4>(1, 1, "DSPSC timed may block ");
546  bench<DSPSC, T, 5>(1, 1, "DSPSC wait may block ");
547  dottedLine();
548  }
549  if (nc == 1) {
550  bench<DMPSC, T, 0>(np, 1, "DMPSC try spin only ");
551  bench<DMPSC, T, 1>(np, 1, "DMPSC timed spin only ");
552  bench<DMPSC, T, 2>(np, 1, "DMPSC wait spin only ");
553  bench<DMPSC, T, 3>(np, 1, "DMPSC try may block ");
554  bench<DMPSC, T, 4>(np, 1, "DMPSC timed may block ");
555  bench<DMPSC, T, 5>(np, 1, "DMPSC wait may block ");
556  dottedLine();
557  }
558  if (np == 1) {
559  bench<DSPMC, T, 0>(1, nc, "DSPMC try spin only ");
560  bench<DSPMC, T, 1>(1, nc, "DSPMC timed spin only ");
561  bench<DSPMC, T, 2>(1, nc, "DSPMC wait spin only ");
562  bench<DSPMC, T, 3>(1, nc, "DSPMC try may block ");
563  bench<DSPMC, T, 4>(1, nc, "DSPMC timed may block ");
564  bench<DSPMC, T, 5>(1, nc, "DSPMC wait may block ");
565  dottedLine();
566  }
567  bench<DMPMC, T, 0>(np, nc, "DMPMC try spin only ");
568  bench<DMPMC, T, 1>(np, nc, "DMPMC timed spin only ");
569  bench<DMPMC, T, 2>(np, nc, "DMPMC wait spin only ");
570  bench<DMPMC, T, 3>(np, nc, "DMPMC try may block ");
571  bench<DMPMC, T, 4>(np, nc, "DMPMC timed may block ");
572  bench<DMPMC, T, 5>(np, nc, "DMPMC wait may block ");
573  dottedLine();
574  if (np == 1 && nc == 1) {
575  bench<FPCQ, T, 0>(1, 1, "folly::PCQ read ");
576  dottedLine();
577  }
578  bench<FMPMC, T, 3>(np, nc, "folly::MPMC read ");
579  bench<FMPMC, T, 4>(np, nc, "folly::MPMC tryReadUntil ");
580  bench<FMPMC, T, 5>(np, nc, "folly::MPMC blockingRead ");
581  std::cout << "=============================================================="
582  << std::endl;
583 }
const char * name
Definition: http_parser.c:437
void dottedLine()