Commit a3308c6d by Eric Fiselier

Introduce use of std::chrono and remove Walltime printing

parent 8b0b73f0
...@@ -69,17 +69,6 @@ DEFINE_bool(color_print, true, "Enables colorized logging."); ...@@ -69,17 +69,6 @@ DEFINE_bool(color_print, true, "Enables colorized logging.");
DEFINE_int32(v, 0, "The level of verbose logging to output"); DEFINE_int32(v, 0, "The level of verbose logging to output");
// The ""'s catch people who don't pass in a literal for "str"
#define strliterallen(str) (sizeof("" str "") - 1)
// Must use a string literal for prefix.
#define memprefix(str, len, prefix) \
((((len) >= strliterallen(prefix)) && \
std::memcmp(str, prefix, strliterallen(prefix)) == 0) \
? str + strliterallen(prefix) \
: nullptr)
namespace benchmark { namespace benchmark {
namespace internal { namespace internal {
...@@ -120,23 +109,6 @@ bool use_real_time GUARDED_BY(GetBenchmarkLock()); ...@@ -120,23 +109,6 @@ bool use_real_time GUARDED_BY(GetBenchmarkLock());
// TODO(ericwf): support MallocCounter. // TODO(ericwf): support MallocCounter.
//static benchmark::MallocCounter *benchmark_mc; //static benchmark::MallocCounter *benchmark_mc;
static bool CpuScalingEnabled() {
// On Linux, the CPUfreq subsystem exposes CPU information as files on the
// local file system. If reading the exported files fails, then we may not be
// running on Linux, so we silently ignore all the read errors.
for (int cpu = 0, num_cpus = NumCPUs(); cpu < num_cpus; ++cpu) {
std::string governor_file = StrCat("/sys/devices/system/cpu/cpu", cpu,
"/cpufreq/scaling_governor");
FILE* file = fopen(governor_file.c_str(), "r");
if (!file) break;
char buff[16];
size_t bytes_read = fread(buff, 1, sizeof(buff), file);
fclose(file);
if (memprefix(buff, bytes_read, "performance") == nullptr) return true;
}
return false;
}
struct ThreadStats { struct ThreadStats {
ThreadStats() : bytes_processed(0), items_processed(0) {} ThreadStats() : bytes_processed(0), items_processed(0) {}
int64_t bytes_processed; int64_t bytes_processed;
......
...@@ -65,11 +65,8 @@ bool JSONReporter::ReportContext(const Context& context) { ...@@ -65,11 +65,8 @@ bool JSONReporter::ReportContext(const Context& context) {
// Open context block and print context information. // Open context block and print context information.
out << inner_indent << "\"context\": {\n"; out << inner_indent << "\"context\": {\n";
std::string indent(4, ' '); std::string indent(4, ' ');
int remainder_us;
std::string walltime_value = walltime::Print( std::string walltime_value = LocalDateTimeString();
walltime::Now(), "%Y/%m/%d-%H:%M:%S",
true, // use local timezone
&remainder_us);
out << indent << FormatKV("date", walltime_value) << ",\n"; out << indent << FormatKV("date", walltime_value) << ",\n";
out << indent out << indent
......
...@@ -98,11 +98,7 @@ bool ConsoleReporter::ReportContext(const Context& context) { ...@@ -98,11 +98,7 @@ bool ConsoleReporter::ReportContext(const Context& context) {
context.mhz_per_cpu, context.mhz_per_cpu,
(context.num_cpus > 1) ? "s" : ""); (context.num_cpus > 1) ? "s" : "");
int remainder_us; std::string walltime_str = LocalDateTimeString();
std::string walltime_str = walltime::Print(
walltime::Now(), "%Y/%m/%d-%H:%M:%S",
true, // use local timezone
&remainder_us);
fprintf(stdout, "%s\n", walltime_str.c_str()); fprintf(stdout, "%s\n", walltime_str.c_str());
if (context.cpu_scaling_enabled) { if (context.cpu_scaling_enabled) {
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "internal_macros.h" #include "internal_macros.h"
#include "log.h" #include "log.h"
#include "sleep.h" #include "sleep.h"
#include "string_util.h"
namespace benchmark { namespace benchmark {
namespace { namespace {
...@@ -352,4 +353,32 @@ int NumCPUs(void) { ...@@ -352,4 +353,32 @@ int NumCPUs(void) {
std::call_once(cpuinfo_init, InitializeSystemInfo); std::call_once(cpuinfo_init, InitializeSystemInfo);
return cpuinfo_num_cpus; return cpuinfo_num_cpus;
} }
// The ""'s catch people who don't pass in a literal for "str"
#define strliterallen(str) (sizeof("" str "") - 1)
// Must use a string literal for prefix.
#define memprefix(str, len, prefix) \
((((len) >= strliterallen(prefix)) && \
std::memcmp(str, prefix, strliterallen(prefix)) == 0) \
? str + strliterallen(prefix) \
: nullptr)
bool CpuScalingEnabled() {
// On Linux, the CPUfreq subsystem exposes CPU information as files on the
// local file system. If reading the exported files fails, then we may not be
// running on Linux, so we silently ignore all the read errors.
for (int cpu = 0, num_cpus = NumCPUs(); cpu < num_cpus; ++cpu) {
std::string governor_file = StrCat("/sys/devices/system/cpu/cpu", cpu,
"/cpufreq/scaling_governor");
FILE* file = fopen(governor_file.c_str(), "r");
if (!file) break;
char buff[16];
size_t bytes_read = fread(buff, 1, sizeof(buff), file);
fclose(file);
if (memprefix(buff, bytes_read, "performance") == nullptr) return true;
}
return false;
}
} // end namespace benchmark } // end namespace benchmark
...@@ -6,6 +6,7 @@ double MyCPUUsage(); ...@@ -6,6 +6,7 @@ double MyCPUUsage();
double ChildrenCPUUsage(); double ChildrenCPUUsage();
int NumCPUs(); int NumCPUs();
double CyclesPerSecond(); double CyclesPerSecond();
bool CpuScalingEnabled();
} // end namespace benchmark } // end namespace benchmark
#endif // BENCHMARK_SYSINFO_H_ #endif // BENCHMARK_SYSINFO_H_
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "walltime.h" #include "walltime.h"
#include <sys/time.h> #include <sys/time.h>
#include <iostream>
#include <cstdio> #include <cstdio>
#include <cstdint> #include <cstdint>
...@@ -22,35 +23,17 @@ ...@@ -22,35 +23,17 @@
#include <ctime> #include <ctime>
#include <atomic> #include <atomic>
#include <chrono>
#include <limits> #include <limits>
#include <type_traits> #include <type_traits>
#include "arraysize.h"
#include "check.h" #include "check.h"
#include "cycleclock.h" #include "cycleclock.h"
#include "sysinfo.h" #include "sysinfo.h"
namespace benchmark { namespace benchmark {
namespace walltime { namespace walltime {
namespace {
bool SplitTimezone(WallTime value, bool local, struct tm* t,
double* subsecond) {
memset(t, 0, sizeof(*t));
if ((value < 0) || (value > std::numeric_limits<time_t>::max())) {
*subsecond = 0.0;
return false;
}
const time_t whole_time = static_cast<time_t>(value);
*subsecond = value - whole_time;
if (local)
localtime_r(&whole_time, t);
else
gmtime_r(&whole_time, t);
return true;
}
} // end anonymous namespace
namespace { namespace {
...@@ -163,29 +146,47 @@ WallTimeImp::WallTimeImp() ...@@ -163,29 +146,47 @@ WallTimeImp::WallTimeImp()
} // end anonymous namespace } // end anonymous namespace
// WallTimeImp doesn't work when CPU Scaling is enabled. If CPU Scaling is
// enabled at the start of the program then std::chrono::system_clock is used
// instead.
WallTime Now() WallTime Now()
{ {
static bool useWallTime = !CpuScalingEnabled();
if (useWallTime) {
static WallTimeImp& imp = WallTimeImp::GetWallTimeImp(); static WallTimeImp& imp = WallTimeImp::GetWallTimeImp();
return imp.Now(); return imp.Now();
} else {
typedef std::chrono::system_clock Clock;
typedef std::chrono::duration<WallTime, std::chrono::seconds::period>
FPSeconds;
static_assert(std::chrono::treat_as_floating_point<WallTime>::value,
"This type must be treated as a floating point type.");
auto now = Clock::now().time_since_epoch();
return std::chrono::duration_cast<FPSeconds>(now).count();
}
} }
std::string Print(WallTime time, const char* format, bool local, } // end namespace walltime
int* remainder_us) {
char storage[32];
struct tm split; std::string DateTimeString(bool local) {
double subsecond; typedef std::chrono::system_clock Clock;
if (!SplitTimezone(time, local, &split, &subsecond)) { std::time_t now = Clock::to_time_t(Clock::now());
snprintf(storage, sizeof(storage), "Invalid time: %f", time); char storage[128];
std::tm timeinfo;
if (local) {
std::tm* ret = std::localtime(&now);
CHECK(ret != nullptr);
timeinfo = *ret;
} else { } else {
if (remainder_us != nullptr) { std::tm* ret = std::gmtime(&now);
*remainder_us = static_cast<int>((subsecond * 1000000) + 0.5); CHECK(ret != nullptr);
if (*remainder_us > 999999) *remainder_us = 999999; timeinfo = *ret;
if (*remainder_us < 0) *remainder_us = 0;
}
strftime(storage, sizeof(storage), format, &split);
} }
std::size_t written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo);
CHECK(written < arraysize(storage));
return std::string(storage); return std::string(storage);
} }
} // end namespace walltime
} // end namespace benchmark } // end namespace benchmark
...@@ -8,15 +8,14 @@ typedef double WallTime; ...@@ -8,15 +8,14 @@ typedef double WallTime;
namespace walltime { namespace walltime {
WallTime Now(); WallTime Now();
// GIVEN: walltime, generic format string (as understood by strftime),
// a boolean flag specifying if the time is local or UTC (true=local).
// RETURNS: the formatted string. ALSO RETURNS: the remaining number of
// microseconds (never printed in the string since strftime does not understand
// it)
std::string Print(WallTime time, const char *format, bool local,
int *remainder_us);
} // end namespace walltime } // end namespace walltime
std::string DateTimeString(bool local = false);
inline std::string LocalDateTimeString() {
return DateTimeString(true);
}
} // end namespace benchmark } // end namespace benchmark
#endif // BENCHMARK_WALLTIME_H_ #endif // BENCHMARK_WALLTIME_H_
...@@ -59,6 +59,27 @@ void BM_spin_pause_during(benchmark::State& state) { ...@@ -59,6 +59,27 @@ void BM_spin_pause_during(benchmark::State& state) {
BASIC_BENCHMARK_TEST(BM_spin_pause_during); BASIC_BENCHMARK_TEST(BM_spin_pause_during);
BASIC_BENCHMARK_TEST(BM_spin_pause_during)->ThreadPerCpu(); BASIC_BENCHMARK_TEST(BM_spin_pause_during)->ThreadPerCpu();
void BM_pause_during(benchmark::State& state) {
while(state.KeepRunning()) {
state.PauseTiming();
state.ResumeTiming();
}
}
BASIC_BENCHMARK_TEST(BM_pause_during);
BASIC_BENCHMARK_TEST(BM_pause_during)->ThreadPerCpu();
void BM_pause_during_realtime(benchmark::State& state) {
state.UseRealTime();
while(state.KeepRunning()) {
state.PauseTiming();
state.ResumeTiming();
}
}
BASIC_BENCHMARK_TEST(BM_pause_during_realtime);
BASIC_BENCHMARK_TEST(BM_pause_during_realtime)->ThreadPerCpu();
void BM_spin_pause_after(benchmark::State& state) { void BM_spin_pause_after(benchmark::State& state) {
while(state.KeepRunning()) { while(state.KeepRunning()) {
......
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