#include <folly/detail/PerfScoped.h>
#include <folly/Conv.h>
#if FOLLY_PERF_IS_SUPPORTED
#include <folly/Subprocess.h>
#include <folly/system/Pid.h>
#include <folly/testing/TestUtil.h>
#endif
#include <stdexcept>
#include <thread>
namespace folly {
namespace detail {
#if FOLLY_PERF_IS_SUPPORTED
namespace {
constexpr std::chrono::milliseconds kTerminateTimeout{500};
std::vector<std::string> prependCommonArgs(
const std::vector<std::string>& passed, const test::TemporaryFile* output) {
std::vector<std::string> res{"/usr/bin/perf"};
res.insert(res.end(), passed.begin(), passed.end());
res.push_back("-p");
res.push_back(folly::to<std::string>(get_cached_pid()));
if (output) {
res.push_back("--output");
res.push_back(output->path().string());
}
return res;
}
Subprocess::Options subprocessOptions() {
Subprocess::Options res;
res.terminateChildOnDestruction(kTerminateTimeout);
return res;
}
}
class PerfScoped::PerfScopedImpl {
public:
PerfScopedImpl(const std::vector<std::string>& args, std::string* output)
: proc_(
prependCommonArgs(args, output != nullptr ? &outputFile_ : nullptr),
subprocessOptions()),
output_(output) {}
PerfScopedImpl(const PerfScopedImpl&) = delete;
PerfScopedImpl(PerfScopedImpl&&) = delete;
PerfScopedImpl& operator=(const PerfScopedImpl&) = delete;
PerfScopedImpl& operator=(PerfScopedImpl&&) = delete;
~PerfScopedImpl() noexcept {
proc_.sendSignal(SIGINT);
proc_.wait();
if (output_) {
readFile(outputFile_.fd(), *output_);
}
}
private:
test::TemporaryFile outputFile_;
Subprocess proc_;
std::string* output_;
};
PerfScoped::PerfScoped(
const std::vector<std::string>& args, std::string* output)
: pimpl_(std::make_unique<PerfScopedImpl>(args, output)) {}
#else
class PerfScoped::PerfScopedImpl { … };
[[noreturn]] PerfScoped::PerfScoped(
const std::vector<std::string>& args, std::string* output) { … }
#endif
PerfScoped::PerfScoped() = default;
PerfScoped::PerfScoped(PerfScoped&&) noexcept = default;
PerfScoped& PerfScoped::operator=(PerfScoped&&) noexcept = default;
PerfScoped::~PerfScoped() noexcept = default;
}
}