proxygen
FlatCombiningPriorityQueueTest.cpp File Reference
#include <folly/experimental/FlatCombiningPriorityQueue.h>
#include <folly/Benchmark.h>
#include <folly/portability/GTest.h>
#include <glog/logging.h>
#include <condition_variable>
#include <mutex>
#include <queue>

Go to the source code of this file.

Classes

class  BaselinePQ< T, PriorityQueue, Mutex >
 

Typedefs

using FCPQ = folly::FlatCombiningPriorityQueue< int >
 
using Baseline = BaselinePQ< int >
 

Enumerations

enum  Exp { NoFC, FCNonBlock, FCBlock, FCTimed }
 

Functions

 DEFINE_bool (bench, false,"run benchmark")
 
 DEFINE_int32 (reps, 10,"number of reps")
 
 DEFINE_int32 (ops, 100000,"number of operations per rep")
 
 DEFINE_int32 (size, 64,"initial size of the priority queue")
 
 DEFINE_int32 (work, 1000,"amount of unrelated work per operation")
 
void doWork (int work)
 
template<typename PriorityQueue , typename Func >
static uint64_t run_once (PriorityQueue &pq, const Func &fn)
 
 TEST (FCPriQueue, basic)
 
 TEST (FCPriQueue, bounded)
 
 TEST (FCPriQueue, timeout)
 
 TEST (FCPriQueue, push_pop)
 
static uint64_t test (std::string name, Exp exp, uint64_t base)
 
 TEST (FCPriQueue, bench)
 

Variables

static std::vector< int > nthr = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64}
 
static uint32_t nthreads
 

Typedef Documentation

using Baseline = BaselinePQ<int>

Definition at line 108 of file FlatCombiningPriorityQueueTest.cpp.

using FCPQ = folly::FlatCombiningPriorityQueue<int>

Definition at line 107 of file FlatCombiningPriorityQueueTest.cpp.

Enumeration Type Documentation

enum Exp
Enumerator
NoFC 
FCNonBlock 
FCBlock 
FCTimed 

Definition at line 272 of file FlatCombiningPriorityQueueTest.cpp.

Function Documentation

DEFINE_bool ( bench  ,
false  ,
"run benchmark  
)
DEFINE_int32 ( reps  ,
10  ,
"number of reps"   
)
DEFINE_int32 ( ops  ,
100000  ,
"number of operations per rep"   
)
DEFINE_int32 ( size  ,
64  ,
"initial size of the priority queue"   
)
DEFINE_int32 ( work  ,
1000  ,
"amount of unrelated work per operation"   
)
void doWork ( int  work)

Definition at line 32 of file FlatCombiningPriorityQueueTest.cpp.

References a, folly::doNotOptimizeAway(), i, mutex, Mutex, T, and uint64_t.

Referenced by TEST(), and test().

32  {
33  uint64_t a = 0;
34  for (int i = work; i > 0; --i) {
35  a += i;
36  }
38 }
char a
auto doNotOptimizeAway(const T &datum) -> typename std::enable_if< !detail::DoNotOptimizeAwayNeedsIndirect< T >::value >::type
Definition: Benchmark.h:258
template<typename PriorityQueue , typename Func >
static uint64_t run_once ( PriorityQueue &  pq,
const Func &  fn 
)
static

Definition at line 118 of file FlatCombiningPriorityQueueTest.cpp.

References count, i, now(), nthreads, ops, BaselinePQ< T, PriorityQueue, Mutex >::size(), start, folly::pushmi::detail::t, threads, uint32_t, and uint64_t.

Referenced by TEST(), and test().

118  {
119  int ops = FLAGS_ops;
120  int size = FLAGS_size;
121  std::atomic<bool> start{false};
122  std::atomic<uint32_t> started{0};
123 
124  for (int i = 0; i < size; ++i) {
125  CHECK(pq.try_push(i * (ops / size)));
126  }
127 
128  std::vector<std::thread> threads(nthreads);
129  for (uint32_t tid = 0; tid < nthreads; ++tid) {
130  threads[tid] = std::thread([&, tid] {
131  started.fetch_add(1);
132  while (!start.load()) {
133  /* nothing */;
134  }
135  fn(tid);
136  });
137  }
138 
139  while (started.load() < nthreads) {
140  /* nothing */;
141  }
142  auto tbegin = std::chrono::steady_clock::now();
143 
144  // begin time measurement
145  start.store(true);
146 
147  for (auto& t : threads) {
148  t.join();
149  }
150 
151  // end time measurement
152  uint64_t duration = 0;
153  auto tend = std::chrono::steady_clock::now();
154  duration = std::chrono::duration_cast<std::chrono::nanoseconds>(tend - tbegin)
155  .count();
156  return duration;
157 }
std::chrono::steady_clock::time_point now()
static uint32_t nthreads
std::vector< std::thread::id > threads
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
const int ops
auto start
int * count
TEST ( FCPriQueue  ,
basic   
)

Definition at line 159 of file FlatCombiningPriorityQueueTest.cpp.

References EXPECT_EQ, EXPECT_FALSE, and v.

159  {
160  FCPQ pq;
161  CHECK(pq.empty());
162  CHECK_EQ(pq.size(), 0);
163  int v;
164  CHECK(!pq.try_pop(v));
165  // try_pop() returns an Optional
166  EXPECT_FALSE(bool(pq.try_pop()));
167 
168  CHECK(pq.try_push(1));
169  CHECK(pq.try_push(2));
170  CHECK(!pq.empty());
171  CHECK_EQ(pq.size(), 2);
172 
173  pq.peek(v);
174  CHECK_EQ(v, 2); // higher value has higher priority
175  CHECK(pq.try_peek(v));
176  CHECK_EQ(v, 2);
177  CHECK(!pq.empty());
178  CHECK_EQ(pq.size(), 2);
179 
180  CHECK(pq.try_pop(v));
181  CHECK_EQ(v, 2);
182  CHECK(!pq.empty());
183  CHECK_EQ(pq.size(), 1);
184 
185  CHECK(pq.try_pop(v));
186  CHECK_EQ(v, 1);
187  CHECK(pq.empty());
188  CHECK_EQ(pq.size(), 0);
189 
190  CHECK(pq.try_push(1));
191  CHECK(pq.try_push(2));
192 
193  // check successful try_pop()
194  EXPECT_EQ(*pq.try_pop(), 2);
195  CHECK(!pq.empty());
196  CHECK_EQ(pq.size(), 1);
197 
198  EXPECT_EQ(*pq.try_pop(), 1);
199  CHECK(pq.empty());
200  CHECK_EQ(pq.size(), 0);
201 }
auto v
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
folly::FlatCombiningPriorityQueue< int > FCPQ
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( FCPriQueue  ,
bounded   
)

Definition at line 203 of file FlatCombiningPriorityQueueTest.cpp.

References v.

203  {
204  FCPQ pq(1);
205  CHECK(pq.try_push(1));
206  CHECK(!pq.try_push(1));
207  CHECK_EQ(pq.size(), 1);
208  CHECK(!pq.empty());
209  int v;
210  CHECK(pq.try_pop(v));
211  CHECK_EQ(v, 1);
212  CHECK_EQ(pq.size(), 0);
213  CHECK(pq.empty());
214 }
auto v
folly::FlatCombiningPriorityQueue< int > FCPQ
TEST ( FCPriQueue  ,
timeout   
)

Definition at line 216 of file FlatCombiningPriorityQueueTest.cpp.

References EXPECT_EQ, EXPECT_FALSE, now(), and v.

216  {
217  FCPQ pq(1);
218  int v;
219  CHECK(!pq.try_peek(v));
220  CHECK(!pq.try_pop(v));
221  pq.push(10);
222  CHECK(!pq.try_push(20));
223 
224  auto dur = std::chrono::microseconds(1000);
225  EXPECT_EQ(*pq.try_pop(), 10);
226  CHECK(pq.empty());
227  // check try_***_for
228  EXPECT_FALSE(bool(pq.try_pop_for(dur)));
229  EXPECT_FALSE(bool(pq.try_peek_for(dur)));
230  CHECK(pq.try_push_for(10, dur));
231  CHECK(!pq.try_push_for(20, dur));
232  EXPECT_EQ(*pq.try_peek_for(dur), 10);
233  EXPECT_EQ(*pq.try_pop_for(dur), 10);
234 
235  CHECK(pq.empty());
236  // check try_***_until
237  EXPECT_FALSE(bool(pq.try_pop_until(std::chrono::steady_clock::now() + dur)));
238 
239  EXPECT_FALSE(bool(pq.try_peek_until(std::chrono::steady_clock::now() + dur)));
240  CHECK(pq.try_push_until(10, std::chrono::steady_clock::now() + dur));
241  CHECK(!pq.try_push_until(20, std::chrono::steady_clock::now() + dur));
242  EXPECT_EQ(*pq.try_peek_until(std::chrono::steady_clock::now() + dur), 10);
243  EXPECT_EQ(*pq.try_pop_until(std::chrono::steady_clock::now() + dur), 10);
244  CHECK(pq.empty());
245 }
auto v
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
std::chrono::steady_clock::time_point now()
folly::FlatCombiningPriorityQueue< int > FCPQ
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( FCPriQueue  ,
push_pop   
)

Definition at line 247 of file FlatCombiningPriorityQueueTest.cpp.

References doWork(), EXPECT_NE, i, folly::none, now(), nthreads, ops, run_once(), uint32_t, v, and folly::when().

247  {
248  int ops = 1000;
249  int work = 0;
250  std::chrono::steady_clock::time_point when =
251  std::chrono::steady_clock::now() + std::chrono::hours(24);
252  for (auto n : nthr) {
253  nthreads = n;
254  FCPQ pq(10000);
255  auto fn = [&](uint32_t tid) {
256  for (int i = tid; i < ops; i += nthreads) {
257  CHECK(pq.try_push(i));
258  CHECK(pq.try_push_until(i, when));
259  pq.push(i);
260  doWork(work);
261  int v;
262  CHECK(pq.try_pop(v));
263  EXPECT_NE(pq.try_pop_until(when), folly::none);
264  pq.pop(v);
265  doWork(work);
266  }
267  };
268  run_once(pq, fn);
269  }
270 }
auto v
static uint64_t run_once(PriorityQueue &pq, const Func &fn)
std::chrono::steady_clock::time_point now()
static std::vector< int > nthr
static uint32_t nthreads
void doWork(int work)
folly::FlatCombiningPriorityQueue< int > FCPQ
const int ops
Future< Unit > when(bool p, F &&thunk)
Definition: Future-inl.h:2330
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
constexpr None none
Definition: Optional.h:87
static uint64_t test ( std::string  name,
Exp  exp,
uint64_t  base 
)
static

Definition at line 279 of file FlatCombiningPriorityQueueTest.cpp.

References doWork(), EXPECT_NE, FCBlock, FCNonBlock, FCTimed, i, max, min, name, NoFC, folly::none, now(), nthreads, ops, run_once(), sum(), BaselinePQ< T, PriorityQueue, Mutex >::try_pop(), BaselinePQ< T, PriorityQueue, Mutex >::try_push(), uint32_t, uint64_t, v, and folly::when().

Referenced by TEST().

279  {
280  int ops = FLAGS_ops;
281  int work = FLAGS_work;
282 
283  uint64_t min = UINTMAX_MAX;
284  uint64_t max = 0;
285  uint64_t sum = 0;
286 
287  for (int r = 0; r < FLAGS_reps; ++r) {
288  uint64_t dur;
289  switch (exp) {
290  case NoFC: {
291  Baseline pq;
292  auto fn = [&](uint32_t tid) {
293  for (int i = tid; i < ops; i += nthreads) {
294  CHECK(pq.try_push(i));
295  doWork(work);
296  int v;
297  CHECK(pq.try_pop(v));
298  doWork(work);
299  }
300  };
301  dur = run_once(pq, fn);
302  break;
303  }
304  case FCNonBlock: {
305  FCPQ pq;
306  auto fn = [&](uint32_t tid) {
307  for (int i = tid; i < ops; i += nthreads) {
308  CHECK(pq.try_push(i));
309  doWork(work);
310  int v;
311  CHECK(pq.try_pop(v));
312  doWork(work);
313  }
314  };
315  dur = run_once(pq, fn);
316  break;
317  }
318  case FCBlock: {
319  FCPQ pq;
320  auto fn = [&](uint32_t tid) {
321  for (int i = tid; i < ops; i += nthreads) {
322  pq.push(i);
323  doWork(work);
324  int v;
325  pq.pop(v);
326  doWork(work);
327  }
328  };
329  dur = run_once(pq, fn);
330  break;
331  }
332  case FCTimed: {
333  FCPQ pq;
334  auto fn = [&](uint32_t tid) {
335  std::chrono::steady_clock::time_point when =
336  std::chrono::steady_clock::now() + std::chrono::hours(24);
337  for (int i = tid; i < ops; i += nthreads) {
338  CHECK(pq.try_push_until(i, when));
339  doWork(work);
340  EXPECT_NE(pq.try_pop_until(when), folly::none);
341  doWork(work);
342  }
343  };
344  dur = run_once(pq, fn);
345  break;
346  }
347  default:
348  CHECK(false);
349  }
350 
351  sum += dur;
352  min = std::min(min, dur);
353  max = std::max(max, dur);
354  }
355 
356  uint64_t avg = sum / FLAGS_reps;
357  uint64_t res = min;
358  std::cout << name;
359  std::cout << " " << std::setw(4) << max / FLAGS_ops << " ns";
360  std::cout << " " << std::setw(4) << avg / FLAGS_ops << " ns";
361  std::cout << " " << std::setw(4) << res / FLAGS_ops << " ns";
362  if (base) {
363  std::cout << " " << std::setw(3) << 100 * base / res << "%";
364  }
365  std::cout << std::endl;
366  return res;
367 }
std::atomic< int64_t > sum(0)
auto v
static uint64_t run_once(PriorityQueue &pq, const Func &fn)
LogLevel max
Definition: LogLevel.cpp:31
std::chrono::steady_clock::time_point now()
static uint32_t nthreads
void doWork(int work)
const char * name
Definition: http_parser.c:437
LogLevel min
Definition: LogLevel.cpp:30
folly::FlatCombiningPriorityQueue< int > FCPQ
const int ops
Future< Unit > when(bool p, F &&thunk)
Definition: Future-inl.h:2330
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
constexpr None none
Definition: Optional.h:87
bool try_push(const T &val)
TEST ( FCPriQueue  ,
bench   
)

Definition at line 369 of file FlatCombiningPriorityQueueTest.cpp.

References FCBlock, FCNonBlock, FCTimed, i, NoFC, nthreads, test(), and uint64_t.

369  {
370  if (!FLAGS_bench) {
371  return;
372  }
373 
374  std::cout << "Test_name, Max time, Avg time, Min time, % base min / min"
375  << std::endl;
376  for (int i : nthr) {
377  nthreads = i;
378  std::cout << "\n------------------------------------ Number of threads = "
379  << i << std::endl;
380  uint64_t base = test("baseline ", NoFC, 0);
381  test("baseline - dup ", NoFC, base);
382  std::cout << "---- fc -------------------------------" << std::endl;
383  test("fc non-blocking ", FCNonBlock, base);
384  test("fc non-blocking - dup ", FCNonBlock, base);
385  test("fc timed ", FCTimed, base);
386  test("fc timed - dup ", FCTimed, base);
387  test("fc blocking ", FCBlock, base);
388  test("fc blocking - dup ", FCBlock, base);
389  }
390 }
static std::vector< int > nthr
static uint32_t nthreads
static uint64_t test(std::string name, Exp exp, uint64_t base)

Variable Documentation

std::vector<int> nthr = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64}
static

Definition at line 113 of file FlatCombiningPriorityQueueTest.cpp.

uint32_t nthreads
static

Definition at line 115 of file FlatCombiningPriorityQueueTest.cpp.

Referenced by run_once(), TEST(), and test().