cachelib/cachebench/main.cpp (127 lines of code) (raw):
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/io/async/EventBase.h>
#include <folly/logging/LoggerDB.h>
#include <gflags/gflags.h>
#include <memory>
#include <thread>
#include "cachelib/cachebench/runner/Runner.h"
#include "cachelib/cachebench/runner/Stressor.h"
#include "cachelib/common/Utils.h"
#ifdef CACHEBENCH_FB_ENV
#include "cachelib/cachebench/facebook/FbDep.h"
#include "cachelib/cachebench/facebook/fb303/FB303ThriftServer.h"
#include "cachelib/cachebench/facebook/odsl_exporter/OdslExporter.h"
#include "common/init/Init.h"
#else
#include <folly/init/Init.h>
#include <gflags/gflags.h>
#endif
#ifdef CACHEBENCH_FB_ENV
DEFINE_bool(export_to_ods, true, "Upload cachelib stats to ODS");
DEFINE_int32(fb303_port,
0,
"Port for cachebench fb303 service. If 0, do not export to fb303. "
"If valid, this will disable ODSL export.");
#endif
DEFINE_string(json_test_config,
"",
"path to test config. If empty, use default setting");
DEFINE_uint64(
progress,
60,
"if set, prints progress every X seconds as configured, 0 to disable");
DEFINE_string(progress_stats_file,
"",
"Print detailed stats at each progress interval to this file");
DEFINE_int32(timeout_seconds,
0,
"Maximum allowed seconds for running test. 0 means no timeout");
struct sigaction act;
std::unique_ptr<facebook::cachelib::cachebench::Runner> runnerInstance;
std::unique_ptr<std::thread> stopperThread;
void sigint_handler(int sig_num) {
switch (sig_num) {
case SIGINT:
case SIGTERM: {
if (runnerInstance) {
runnerInstance->abort();
}
break;
}
}
}
void setupSignalHandler() {
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = &sigint_handler;
act.sa_flags = SA_RESETHAND;
if (sigaction(SIGINT, &act, nullptr) == -1 ||
sigaction(SIGTERM, &act, nullptr) == -1) {
std::cout << "Failed to register SIGINT&SIGTERM handler" << std::endl;
std::exit(1);
}
}
void setupTimeoutHandler() {
if (FLAGS_timeout_seconds > 0) {
stopperThread.reset(new std::thread([] {
folly::EventBase eb;
eb.runAfterDelay(
[]() {
if (runnerInstance) {
runnerInstance->abort();
}
},
FLAGS_timeout_seconds * 1000);
eb.loopForever();
}));
stopperThread->detach();
}
}
bool checkArgsValidity() {
if (FLAGS_json_test_config.empty() ||
!facebook::cachelib::util::pathExists(FLAGS_json_test_config)) {
std::cout << "Invalid config file: " << FLAGS_json_test_config
<< ". pass a valid --json_test_config for cachebench."
<< std::endl;
return false;
}
return true;
}
int main(int argc, char** argv) {
using namespace facebook::cachelib::cachebench;
#ifdef CACHEBENCH_FB_ENV
facebook::initFacebook(&argc, &argv);
if (!checkArgsValidity()) {
return 1;
}
CacheBenchConfig config(FLAGS_json_test_config,
customizeCacheConfigForFacebook,
customizeStressorConfigForFacebook);
std::unique_ptr<OdslExporter> odslExporter_;
std::unique_ptr<FB303ThriftService> fb303_;
if (FLAGS_fb303_port == 0 && FLAGS_export_to_ods) {
odslExporter_ = std::make_unique<OdslExporter>();
} else if (FLAGS_fb303_port > 0) {
fb303_ = std::make_unique<FB303ThriftService>(FLAGS_fb303_port);
}
std::cout << "Welcome to FB-internal version of cachebench" << std::endl;
#else
folly::init(&argc, &argv, true);
if (!checkArgsValidity()) {
return 1;
}
CacheBenchConfig config(FLAGS_json_test_config);
std::cout << "Welcome to OSS version of cachebench" << std::endl;
#endif
try {
runnerInstance =
std::make_unique<facebook::cachelib::cachebench::Runner>(config);
setupSignalHandler();
setupTimeoutHandler();
return runnerInstance->run(std::chrono::seconds(FLAGS_progress),
FLAGS_progress_stats_file)
? 0
: 1;
} catch (const std::exception& e) {
std::cout << "Invalid configuration. Exception: " << e.what() << std::endl;
return 1;
}
}