in cachelib/benchmarks/ItemsReaperBench.cpp [62:158]
int main(int argc, char** argv) {
folly::init(&argc, &argv);
XLOG(INFO) << "initializing cache";
LruAllocator::AccessConfig accessConfig(
folly::findLastSet(FLAGS_num_keys) + 1, 10);
LruAllocator::Config lruConfig;
lruConfig.setCacheSize(FLAGS_size_gb * 1024 * 1024 * 1024);
lruConfig.setAccessConfig(accessConfig);
lruConfig.enableItemReaperInBackground(
std::chrono::milliseconds{FLAGS_sleep_ms},
util::Throttler::Config{FLAGS_sleep_ms, FLAGS_work_ms});
assert(lruConfig.itemsReaperEnabled());
LruAllocator cache(lruConfig);
const auto poolId =
cache.addPool("default", cache.getCacheMemoryStats().cacheSize);
XLOG(INFO) << "allocating items";
std::mt19937 gen(folly::Random::rand32());
std::normal_distribution<> sizeDis(kAllocSizeMean, kAllocSizeDev);
std::uniform_int_distribution<uint32_t> keySize(kMinKeySize, kMaxKeySize);
std::uniform_int_distribution<uint32_t> ttlDist(0,
FLAGS_benchmark_duration_s);
std::uniform_int_distribution<uint8_t> charDis(0, 25);
for (uint64_t i = 0; i < FLAGS_num_keys; ++i) {
util::allocateAccessible(
cache, poolId,
facebook::cachelib::test_util::getRandomAsciiStr(keySize(gen)),
getRandomAllocSize(sizeDis(gen)), ttlDist(gen));
}
auto reaperStatStr = [](const facebook::cachelib::ReaperStats& stats) {
auto str = folly::sformat(
"numTraversals: {:8d}, numVisits: {:12d}, lastTraversalMs: {:6d}ms, "
"avgTraversalMs: {:6d}ms, maxTraversalMs: {:6d}",
stats.numTraversals, stats.numVisitedItems, stats.lastTraversalTimeMs,
stats.avgTraversalTimeMs, stats.maxTraversalTimeMs);
return str;
};
struct rusage rUsageBefore = {};
struct rusage rUsageAfter = {};
XLOG(INFO) << "Gathering reaper metrics";
if (::getrusage(RUSAGE_SELF, &rUsageBefore)) {
XLOG(INFO) << "Error getting rusage" << errno;
return 0;
}
const auto start = std::chrono::steady_clock::now();
const auto startStats = cache.getReaperStats();
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
if (FLAGS_print_interval_s) {
XLOG_EVERY_MS(INFO, FLAGS_print_interval_s * 1000)
<< reaperStatStr(cache.getReaperStats());
}
if (std::chrono::steady_clock::now() - start >
std::chrono::seconds(FLAGS_benchmark_duration_s)) {
break;
}
}
if (::getrusage(RUSAGE_SELF, &rUsageAfter)) {
XLOG(INFO) << "Error getting rusage" << errno;
return 0;
}
auto finalStats = cache.getReaperStats();
double memoryScanned =
FLAGS_size_gb * (finalStats.numTraversals - startStats.numTraversals);
auto timeTaken = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::steady_clock::now() - start);
XLOG(INFO) << reaperStatStr(finalStats);
XLOG(INFO) << folly::sformat("bytes scanned : {:12.2f}gb/sec",
memoryScanned / timeTaken.count());
auto getTimeRUsage = [](const struct rusage& r) {
double userSeconds = r.ru_utime.tv_sec + r.ru_utime.tv_usec / 1e6;
double sysSeconds = r.ru_stime.tv_sec + r.ru_stime.tv_usec / 1e6;
return std::make_tuple(userSeconds, sysSeconds, userSeconds + sysSeconds);
};
auto [beforeUser, beforeSys, beforeTot] = getTimeRUsage(rUsageBefore);
auto [afterUser, afterSys, afterTot] = getTimeRUsage(rUsageAfter);
// compute core cpu util by divinding the time spent on a core with overall
// time spent to complete the operation.
XLOG(INFO) << folly::sformat(
"cpu util: user: {:3.6}s sys: {:3.6f}s total: {:3.6f}s util-pct: "
"{:2.2f}%",
afterUser - beforeUser, afterSys - beforeSys, afterTot - beforeTot,
100.0 * (afterTot - beforeTot) / timeTaken.count());
return 0;
}