in cachelib/benchmarks/BucketMutexBench.cpp [195:287]
void runBench(Stats& global) {
std::vector<std::thread> threads;
ArrayCounters<Mutex> counters{FLAGS_sizepower, FLAGS_lockpower};
// thread local stats.
std::vector<Stats> stats(FLAGS_num_threads);
// count of number of threads completed
std::atomic<unsigned int> nCompleted{0};
// main thread will wait on this to figure out when the benchmark is
// complete
std::mutex benchFinishMutex;
bool benchFinished = false;
std::condition_variable benchFinishCV;
// all benchmark threads will wait on this after completing the benchmark
// and before doing the thread cleanup.
bool cleanUpStart = false;
std::condition_variable cleanupCV;
std::mutex cleanupMutex;
auto runInThread = [&](unsigned int index) {
auto rng = folly::ThreadLocalPRNG();
std::mt19937 gen(folly::Random::rand32(rng));
std::uniform_real_distribution<> opDis(0, 1);
auto& s = stats[index];
const auto now = util::getCurrentTimeNs();
const size_t numOps = 1ULL << FLAGS_opspower;
for (size_t i = 0; i < numOps; i++) {
const auto r = opDis(gen);
if (r < gLoadInfo.readRatio) {
++s.numReads;
counters.doRead(rng, r < FLAGS_hot_access_pct);
}
if (r < gLoadInfo.writeRatio) {
++s.numWrites;
counters.doWrite(rng, r < FLAGS_hot_access_pct);
}
}
s.elapsedNSecs += (util::getCurrentTimeNs() - now);
if (++nCompleted == FLAGS_num_threads) {
{
std::unique_lock<std::mutex> l(benchFinishMutex);
benchFinished = true;
}
benchFinishCV.notify_one();
}
std::unique_lock<std::mutex> l(cleanupMutex);
cleanupCV.wait(l, [&] { return cleanUpStart; });
};
struct rusage rUsageBefore = {};
struct rusage rUsageAfter = {};
BENCHMARK_SUSPEND {
getrusage(RUSAGE_SELF, &rUsageBefore);
for (size_t i = 0; i < FLAGS_num_threads; i++) {
threads.push_back(std::thread{runInThread, i});
}
}
{
// wait for benchmark to finish.
std::unique_lock<std::mutex> l(benchFinishMutex);
benchFinishCV.wait(l, [&] { return benchFinished; });
}
BENCHMARK_SUSPEND {
{
std::unique_lock<std::mutex> l(cleanupMutex);
cleanUpStart = true;
}
cleanupCV.notify_all();
for (auto& thread : threads) {
thread.join();
}
getrusage(RUSAGE_SELF, &rUsageAfter);
for (auto& stat : stats) {
global += stat;
}
global.numVCsw += rUsageAfter.ru_nvcsw - rUsageBefore.ru_nvcsw;
global.numInvCsw += rUsageAfter.ru_nivcsw - rUsageBefore.ru_nivcsw;
}
}