Commit da9ec3df by Ori Livneh

Include system load average in console and JSON reports

High system load can skew benchmark results. By including system load averages in the library's output, we help users identify a potential issue in the quality of their measurements, and thus assist them in producing better (more reproducible) results. I got the idea for this from Brendan Gregg's checklist for benchmark accuracy (http://www.brendangregg.com/blog/2018-06-30/benchmarking-checklist.html).
parent 1f35fa4a
...@@ -1242,6 +1242,7 @@ struct CPUInfo { ...@@ -1242,6 +1242,7 @@ struct CPUInfo {
double cycles_per_second; double cycles_per_second;
std::vector<CacheInfo> caches; std::vector<CacheInfo> caches;
bool scaling_enabled; bool scaling_enabled;
std::vector<double> load_avg;
static const CPUInfo& Get(); static const CPUInfo& Get();
......
...@@ -111,6 +111,12 @@ bool JSONReporter::ReportContext(const Context& context) { ...@@ -111,6 +111,12 @@ bool JSONReporter::ReportContext(const Context& context) {
} }
indent = std::string(4, ' '); indent = std::string(4, ' ');
out << indent << "],\n"; out << indent << "],\n";
out << indent << "\"load_avg\": [";
for (auto it = info.load_avg.begin(); it != info.load_avg.end();) {
out << *it++;
if (it != info.load_avg.end()) out << ",";
}
out << "],\n";
#if defined(NDEBUG) #if defined(NDEBUG)
const char build_type[] = "release"; const char build_type[] = "release";
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <vector> #include <vector>
#include "check.h" #include "check.h"
#include "string_util.h"
namespace benchmark { namespace benchmark {
...@@ -54,6 +55,14 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out, ...@@ -54,6 +55,14 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out,
Out << "\n"; Out << "\n";
} }
} }
if (!info.load_avg.empty()) {
Out << "Load Average: ";
for (auto It = info.load_avg.begin(); It != info.load_avg.end();) {
Out << StrFormat("%.2f", *It++);
if (It != info.load_avg.end()) Out << ", ";
}
Out << "\n";
}
if (info.scaling_enabled) { if (info.scaling_enabled) {
Out << "***WARNING*** CPU scaling is enabled, the benchmark " Out << "***WARNING*** CPU scaling is enabled, the benchmark "
......
...@@ -571,6 +571,24 @@ double GetCPUCyclesPerSecond() { ...@@ -571,6 +571,24 @@ double GetCPUCyclesPerSecond() {
return static_cast<double>(cycleclock::Now() - start_ticks); return static_cast<double>(cycleclock::Now() - start_ticks);
} }
std::vector<double> GetLoadAvg() {
#if defined BENCHMARK_OS_FREEBSD || defined(BENCHMARK_OS_LINUX) || \
defined BENCHMARK_OS_MACOSX || defined BENCHMARK_OS_NETBSD || \
defined BENCHMARK_OS_OPENBSD
constexpr int kMaxSamples = 3;
std::vector<double> res(kMaxSamples, 0.0);
const int nelem = getloadavg(res.data(), kMaxSamples);
if (nelem < 1) {
res.clear();
} else {
res.resize(nelem);
}
return res;
#else
return {};
#endif
}
} // end namespace } // end namespace
const CPUInfo& CPUInfo::Get() { const CPUInfo& CPUInfo::Get() {
...@@ -582,6 +600,7 @@ CPUInfo::CPUInfo() ...@@ -582,6 +600,7 @@ CPUInfo::CPUInfo()
: num_cpus(GetNumCPUs()), : num_cpus(GetNumCPUs()),
cycles_per_second(GetCPUCyclesPerSecond()), cycles_per_second(GetCPUCyclesPerSecond()),
caches(GetCacheSizes()), caches(GetCacheSizes()),
scaling_enabled(CpuScalingEnabled(num_cpus)) {} scaling_enabled(CpuScalingEnabled(num_cpus)),
load_avg(GetLoadAvg()) {}
} // end namespace benchmark } // end namespace benchmark
...@@ -28,7 +28,8 @@ static int AddContextCases() { ...@@ -28,7 +28,8 @@ static int AddContextCases() {
{"\"mhz_per_cpu\": %float,$", MR_Next}, {"\"mhz_per_cpu\": %float,$", MR_Next},
{"\"cpu_scaling_enabled\": ", MR_Next}, {"\"cpu_scaling_enabled\": ", MR_Next},
{"\"caches\": \\[$", MR_Next}}); {"\"caches\": \\[$", MR_Next}});
auto const& Caches = benchmark::CPUInfo::Get().caches; auto const& Info = benchmark::CPUInfo::Get();
auto const& Caches = Info.caches;
if (!Caches.empty()) { if (!Caches.empty()) {
AddCases(TC_ConsoleErr, {{"CPU Caches:$", MR_Next}}); AddCases(TC_ConsoleErr, {{"CPU Caches:$", MR_Next}});
} }
...@@ -45,8 +46,13 @@ static int AddContextCases() { ...@@ -45,8 +46,13 @@ static int AddContextCases() {
{"\"num_sharing\": %int$", MR_Next}, {"\"num_sharing\": %int$", MR_Next},
{"}[,]{0,1}$", MR_Next}}); {"}[,]{0,1}$", MR_Next}});
} }
AddCases(TC_JSONOut, {{"],$"}}); AddCases(TC_JSONOut, {{"],$"}});
auto const& LoadAvg = Info.load_avg;
if (!LoadAvg.empty()) {
AddCases(TC_ConsoleErr,
{{"Load Average: (%float, ){0,2}%float$", MR_Next}});
}
AddCases(TC_JSONOut, {{"\"load_avg\": \\[(%float,?){0,3}],$", MR_Next}});
return 0; return 0;
} }
int dummy_register = AddContextCases(); int dummy_register = AddContextCases();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment