OsPerfState saves for all CPUs

This commit is contained in:
Carl Pearson
2019-09-26 10:58:01 -05:00
parent d576ac099d
commit 1b3cf604a8
4 changed files with 62 additions and 32 deletions

View File

@@ -148,9 +148,9 @@ See [examples/os_perf.cpp](examples/os_perf.cpp).
#include "perfect/os_perf.hpp"
```
* `Result get_os_perf_state(OsPerfState *state, const int cpu)`: Save the current OS governor mode for CPU `cpu`.
* `Result get_os_perf_state(OsPerfState &state)`: Save the current OS governor mode for all CPUs.
* `Result os_perf_state_maximum(const int cpu)`: Set the OS governor to it's maximum performance mode.
* `Result set_os_perf_state(const int cpu, OsPerfState state)`: Restore a previously-saved OS governor mode.
* `Result set_os_perf_state(OsPerfState state)`: Restore a previously-saved OS governor mode.
### GPU Turbo
@@ -270,3 +270,7 @@ heap: 93824994414192
* [easyperf.net](https://easyperf.net/blog/2019/08/02/Perf-measurement-environment-on-Linux#2-disable-hyper-threading) blog post discussing ACPI/Intel turbo, SMT, Linux governor, CPU affinity, process priority, file system caches, and ASLR.
* [temci](https://github.com/parttimenerd/temci) benchmarking tool for cpu sheilding and disabling hyperthreading, among other things.
* [perflock](https://github.com/aclements/perflock) tool for locking CPU frequency scaling domains
## Acks
Uses [muellan/clipp](https://github.com/muellan/clipp) for cli option parsing.

View File

@@ -5,23 +5,20 @@
int main(void) {
perfect::init();
std::map<int, perfect::OsPerfState> states;
// os performance state for each cpu
perfect::OsPerfState state;
// store the current state
PERFECT(perfect::get_os_perf_state(state));
// max state for each cpu
for (auto cpu : perfect::cpus()) {
perfect::OsPerfState state;
perfect::Result result;
result = perfect::get_os_perf_state(&state, cpu);
if (perfect::Result::SUCCESS == result) {
states[cpu] = state;
}
perfect::os_perf_state_maximum(cpu);
PERFECT(perfect::os_perf_state_maximum(cpu));
}
// do things with all CPUs set to the maximum performancem mode by the OS
for (auto kv : states) {
int cpu = kv.first;
perfect::OsPerfState state = kv.second;
perfect::set_os_perf_state(cpu, state);
}
// restore original state
PERFECT(perfect::set_os_perf_state(state));
}

View File

@@ -3,6 +3,7 @@
#include <vector>
#include <string>
#include <cassert>
#include <map>
#ifdef __linux__
#include "detail/os/linux.hpp"
@@ -17,19 +18,23 @@ namespace perfect {
struct OsPerfState {
#ifdef __linux__
std::string governor;
std::map<int, std::string> governors;
#else
#error "unsupported platform"
#endif
};
Result get_os_perf_state(OsPerfState *state, const int cpu) {
assert(state);
Result get_os_perf_state(OsPerfState &state) {
#ifdef __linux__
return get_governor(state->governor, cpu);
for (auto cpu : cpus()) {
std::string gov;
PERFECT_SUCCESS_OR_RETURN(get_governor(gov, cpu));
state.governors[cpu] = gov;
}
#else
#error "unsupported platform"
#endif
return Result::SUCCESS;
}
Result os_perf_state_maximum(const int cpu) {
@@ -48,13 +53,15 @@ Result os_perf_state_minimum(const int cpu) {
#endif
}
Result set_os_perf_state(const int cpu, OsPerfState state) {
#ifdef __linux__
return set_governor(cpu, state.governor);
Result set_os_perf_state(OsPerfState state) {
#ifdef __linux__
for (auto kv : state.governors) {
PERFECT_SUCCESS_OR_RETURN(set_governor(kv.first, kv.second));
}
#else
#error "unsupported platform"
#endif
return Result::SUCCESS;
}
};

View File

@@ -13,6 +13,7 @@
#include "perfect/aslr.hpp"
#include "perfect/cpu_set.hpp"
#include "perfect/cpu_turbo.hpp"
#include "perfect/os_perf.hpp"
#include "perfect/detail/os/linux.hpp"
// argv should be null-terminated
@@ -66,10 +67,11 @@ int fork_child(char *const *argv) {
int main(int argc, char **argv) {
using namespace clipp;
int numUnshielded = 0;
int numShielded = 0;
bool noAslr = false;
bool noCpuTurbo = false;
size_t numUnshielded = 0;
size_t numShielded = 0;
bool aslr = false;
bool cpuTurbo = false;
bool maxOsPerf = true;
std::vector<std::string> program;
@@ -79,8 +81,11 @@ int main(int argc, char **argv) {
(option("-s") &
value("SH", numShielded).doc("number of shielded CPUs")));
auto cli = (shieldGroup, option("--no-aslr").set(noAslr).doc("disable ASLR"),
option("--no-cpu-turbo").set(noCpuTurbo).doc("disable CPU turbo"),
auto cli = (shieldGroup,
option("--no-max-perf").set(maxOsPerf, false).doc("do not max os perf"),
option("--no-aslr").set(aslr, false).doc("disable ASLR"),
option("--no-cpu-turbo").set(cpuTurbo, false).doc("disable CPU turbo"),
// run everything after "--"
required("--") & greedy(values("cmd", program))
@@ -139,17 +144,29 @@ int main(int argc, char **argv) {
}
// handle aslr
if (noAslr) {
if (!aslr) {
std::cerr << "disable ASLR for this process\n";
PERFECT(perfect::disable_aslr());
}
// handle CPU turbo
perfect::CpuTurboState cpuTurboState;
if (noCpuTurbo) {
if (!cpuTurbo) {
std::cerr << "disabling cpu turbo\n";
PERFECT(perfect::get_cpu_turbo_state(&cpuTurboState));
PERFECT(perfect::disable_cpu_turbo());
}
// handle governor
perfect::OsPerfState osPerfState;
if (maxOsPerf) {
std::cerr << "set max performance state\n";
PERFECT(perfect::get_os_perf_state(osPerfState));
for (auto cpu : perfect::cpus()) {
PERFECT(perfect::os_perf_state_maximum(cpu));
}
}
// parent should return
std::cerr << "exec ";
for (size_t i = 0; i < args.size() - 1; ++i) {
@@ -167,10 +184,15 @@ int main(int argc, char **argv) {
}
// restore original turbo state
if (noCpuTurbo) {
if (!cpuTurbo) {
std::cerr << "restore CPU turbo\n";
PERFECT(perfect::set_cpu_turbo_state(cpuTurboState));
}
if (maxOsPerf) {
std::cerr << "restore os performance state\n";
PERFECT(perfect::set_os_perf_state(osPerfState));
}
return status;
}