20 #include <glog/logging.h> 22 #include <condition_variable> 30 DEFINE_int32(work, 1000,
"amount of unrelated work per operation");
34 for (
int i = work;
i > 0; --
i) {
44 typename PriorityQueue = std::priority_queue<T>,
50 typename = decltype(PriorityQueue(std::declval<PQArgs>()...))>
55 std::lock_guard<Mutex>
g(
m_);
60 std::lock_guard<Mutex>
g(
m_);
65 std::lock_guard<Mutex>
g(
m_);
74 }
catch (
const std::bad_alloc&) {
80 std::lock_guard<Mutex>
g(
m_);
91 std::lock_guard<Mutex>
g(
m_);
107 using FCPQ = folly::FlatCombiningPriorityQueue<int>;
110 #if FOLLY_SANITIZE_THREAD 111 static std::vector<int>
nthr = {1, 2, 3, 4, 6, 8, 12, 16};
113 static std::vector<int> nthr = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64};
117 template <
typename PriorityQueue,
typename Func>
120 int size = FLAGS_size;
121 std::atomic<bool>
start{
false};
122 std::atomic<uint32_t> started{0};
124 for (
int i = 0;
i <
size; ++
i) {
125 CHECK(pq.try_push(
i * (ops / size)));
130 threads[tid] = std::thread([&, tid] {
131 started.fetch_add(1);
132 while (!
start.load()) {
147 for (
auto&
t : threads) {
154 duration = std::chrono::duration_cast<std::chrono::nanoseconds>(tend - tbegin)
162 CHECK_EQ(pq.size(), 0);
164 CHECK(!pq.try_pop(v));
168 CHECK(pq.try_push(1));
169 CHECK(pq.try_push(2));
171 CHECK_EQ(pq.size(), 2);
175 CHECK(pq.try_peek(v));
178 CHECK_EQ(pq.size(), 2);
180 CHECK(pq.try_pop(v));
183 CHECK_EQ(pq.size(), 1);
185 CHECK(pq.try_pop(v));
188 CHECK_EQ(pq.size(), 0);
190 CHECK(pq.try_push(1));
191 CHECK(pq.try_push(2));
196 CHECK_EQ(pq.size(), 1);
200 CHECK_EQ(pq.size(), 0);
205 CHECK(pq.try_push(1));
206 CHECK(!pq.try_push(1));
207 CHECK_EQ(pq.size(), 1);
210 CHECK(pq.try_pop(v));
212 CHECK_EQ(pq.size(), 0);
219 CHECK(!pq.try_peek(v));
220 CHECK(!pq.try_pop(v));
222 CHECK(!pq.try_push(20));
224 auto dur = std::chrono::microseconds(1000);
230 CHECK(pq.try_push_for(10, dur));
231 CHECK(!pq.try_push_for(20, dur));
250 std::chrono::steady_clock::time_point
when =
252 for (
auto n : nthr) {
257 CHECK(pq.try_push(
i));
258 CHECK(pq.try_push_until(
i, when));
262 CHECK(pq.try_pop(v));
281 int work = FLAGS_work;
287 for (
int r = 0; r < FLAGS_reps; ++r) {
308 CHECK(pq.try_push(
i));
311 CHECK(pq.try_pop(v));
335 std::chrono::steady_clock::time_point
when =
338 CHECK(pq.try_push_until(
i, when));
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";
363 std::cout <<
" " << std::setw(3) << 100 * base / res <<
"%";
365 std::cout << std::endl;
374 std::cout <<
"Test_name, Max time, Avg time, Min time, % base min / min" 378 std::cout <<
"\n------------------------------------ Number of threads = " 381 test(
"baseline - dup ",
NoFC, base);
382 std::cout <<
"---- fc -------------------------------" << std::endl;
DEFINE_int32(reps, 10,"number of reps")
std::atomic< int64_t > sum(0)
static uint64_t run_once(PriorityQueue &pq, const Func &fn)
#define EXPECT_EQ(val1, val2)
std::chrono::steady_clock::time_point now()
std::condition_variable notempty_
static std::vector< int > nthr
std::condition_variable notfull_
std::vector< std::thread::id > threads
constexpr auto size(C const &c) -> decltype(c.size())
folly::FlatCombiningPriorityQueue< int > FCPQ
BaselinePQ(size_t maxSize=0, PQArgs...args)
Future< Unit > when(bool p, F &&thunk)
#define EXPECT_NE(val1, val2)
static uint64_t test(std::string name, Exp exp, uint64_t base)
DEFINE_bool(bench, false,"run benchmark")
#define EXPECT_FALSE(condition)
uint64_t bench(const int nprod, const int ncons, const std::string &name)
auto doNotOptimizeAway(const T &datum) -> typename std::enable_if< !detail::DoNotOptimizeAwayNeedsIndirect< T >::value >::type
bool try_push(const T &val)