18 #ifdef BENCHMARK_OS_WINDOWS
20 #undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA
21 #include <versionhelpers.h>
25 #ifndef BENCHMARK_OS_FUCHSIA
26 #include <sys/resource.h>
29 #include <sys/types.h>
31 #if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_DRAGONFLY || \
32 defined BENCHMARK_OS_MACOSX
33 #include <sys/sysctl.h>
35 #if defined(BENCHMARK_OS_MACOSX)
36 #include <mach/mach_init.h>
37 #include <mach/mach_port.h>
38 #include <mach/thread_act.h>
42 #ifdef BENCHMARK_OS_EMSCRIPTEN
43 #include <emscripten.h>
65 #pragma GCC diagnostic ignored "-Wunused-function"
69 #if defined(BENCHMARK_OS_WINDOWS)
70 double MakeTime(FILETIME
const& kernel_time, FILETIME
const& user_time) {
71 ULARGE_INTEGER kernel;
73 kernel.HighPart = kernel_time.dwHighDateTime;
74 kernel.LowPart = kernel_time.dwLowDateTime;
75 user.HighPart = user_time.dwHighDateTime;
76 user.LowPart = user_time.dwLowDateTime;
77 return (
static_cast<double>(kernel.QuadPart) +
78 static_cast<double>(user.QuadPart)) *
81 #elif !defined(BENCHMARK_OS_FUCHSIA)
82 double MakeTime(
struct rusage
const& ru) {
83 return (
static_cast<double>(ru.ru_utime.tv_sec) +
84 static_cast<double>(ru.ru_utime.tv_usec) * 1e-6 +
85 static_cast<double>(ru.ru_stime.tv_sec) +
86 static_cast<double>(ru.ru_stime.tv_usec) * 1e-6);
89 #if defined(BENCHMARK_OS_MACOSX)
90 double MakeTime(thread_basic_info_data_t
const& info) {
91 return (
static_cast<double>(info.user_time.seconds) +
92 static_cast<double>(info.user_time.microseconds) * 1e-6 +
93 static_cast<double>(info.system_time.seconds) +
94 static_cast<double>(info.system_time.microseconds) * 1e-6);
97 #if defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_THREAD_CPUTIME_ID)
98 double MakeTime(
struct timespec
const& ts) {
99 return ts.tv_sec + (
static_cast<double>(ts.tv_nsec) * 1e-9);
104 std::cerr <<
"ERROR: " <<
msg << std::endl;
105 std::exit(EXIT_FAILURE);
111 #if defined(BENCHMARK_OS_WINDOWS)
112 HANDLE proc = GetCurrentProcess();
113 FILETIME creation_time;
115 FILETIME kernel_time;
117 if (GetProcessTimes(proc, &creation_time, &exit_time, &kernel_time,
119 return MakeTime(kernel_time, user_time);
120 DiagnoseAndExit(
"GetProccessTimes() failed");
121 #elif defined(BENCHMARK_OS_EMSCRIPTEN)
126 return emscripten_get_now() * 1e-3;
127 #elif defined(CLOCK_PROCESS_CPUTIME_ID) && !defined(BENCHMARK_OS_MACOSX)
130 struct timespec
spec;
131 if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &
spec) == 0)
132 return MakeTime(
spec);
133 DiagnoseAndExit(
"clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) failed");
136 if (getrusage(RUSAGE_SELF, &ru) == 0)
return MakeTime(ru);
137 DiagnoseAndExit(
"getrusage(RUSAGE_SELF, ...) failed");
142 #if defined(BENCHMARK_OS_WINDOWS)
143 HANDLE this_thread = GetCurrentThread();
144 FILETIME creation_time;
146 FILETIME kernel_time;
148 GetThreadTimes(this_thread, &creation_time, &exit_time, &kernel_time,
150 return MakeTime(kernel_time, user_time);
151 #elif defined(BENCHMARK_OS_MACOSX)
154 mach_msg_type_number_t
count = THREAD_BASIC_INFO_COUNT;
155 thread_basic_info_data_t info;
156 mach_port_t
thread = pthread_mach_thread_np(pthread_self());
157 if (thread_info(
thread, THREAD_BASIC_INFO, (thread_info_t)&info, &
count) ==
159 return MakeTime(info);
161 DiagnoseAndExit(
"ThreadCPUUsage() failed when evaluating thread_info");
162 #elif defined(BENCHMARK_OS_EMSCRIPTEN)
165 #elif defined(BENCHMARK_OS_RTEMS)
169 #elif defined(BENCHMARK_OS_SOLARIS)
171 if (getrusage(RUSAGE_LWP, &ru) == 0)
return MakeTime(ru);
172 DiagnoseAndExit(
"getrusage(RUSAGE_LWP, ...) failed");
173 #elif defined(CLOCK_THREAD_CPUTIME_ID)
175 if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0)
return MakeTime(ts);
176 DiagnoseAndExit(
"clock_gettime(CLOCK_THREAD_CPUTIME_ID, ...) failed");
178 #error Per-thread timing is not available on your system.
184 typedef std::chrono::system_clock Clock;
186 const std::size_t kTzOffsetLen = 6;
187 const std::size_t kTimestampLen = 19;
190 std::size_t timestamp_len;
191 long int offset_minutes;
192 char tz_offset_sign =
'+';
205 #if defined(BENCHMARK_OS_WINDOWS)
209 std::tm *timeinfo_p = &timeinfo;
210 ::localtime_r(&
now, &timeinfo);
213 tz_len = std::strftime(tz_offset,
sizeof(tz_offset),
"%z", timeinfo_p);
215 if (tz_len < kTzOffsetLen && tz_len > 1) {
220 offset_minutes = ::strtol(tz_offset, NULL, 10);
221 if (offset_minutes < 0) {
222 offset_minutes *= -1;
223 tz_offset_sign =
'-';
226 tz_len = ::snprintf(tz_offset,
sizeof(tz_offset),
"%c%02li:%02li",
227 tz_offset_sign, offset_minutes / 100, offset_minutes % 100);
233 #if defined(BENCHMARK_OS_WINDOWS)
235 timeinfo_p = ::gmtime(&
now);
237 ::gmtime_r(&
now, &timeinfo);
240 strncpy(tz_offset,
"-00:00", kTzOffsetLen + 1);
243 timestamp_len = std::strftime(
storage,
sizeof(
storage),
"%Y-%m-%dT%H:%M:%S",
245 BM_CHECK(timestamp_len == kTimestampLen);
247 ((void)kTimestampLen);
249 std::strncat(
storage, tz_offset,
sizeof(
storage) - timestamp_len - 1);