18 #ifdef BENCHMARK_OS_WINDOWS
20 #include <VersionHelpers.h>
24 #include <sys/resource.h>
26 #include <sys/types.h>
28 #if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX
29 #include <sys/sysctl.h>
53 double cpuinfo_cycles_per_second = 1.0;
54 int cpuinfo_num_cpus = 1;
56 #if !defined BENCHMARK_OS_MACOSX
57 const int64_t estimate_time_ms = 1000;
61 int64_t EstimateCyclesPerSecond() {
68 #if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN
71 bool ReadIntFromFile(
const char* file,
long*
value) {
73 int fd = open(file, O_RDONLY);
77 memset(line,
'\0',
sizeof(line));
78 ssize_t read_err = read(fd, line,
sizeof(line) - 1);
81 const long temp_value = strtol(line, &
err, 10);
82 if (line[0] !=
'\0' && (*
err ==
'\n' || *
err ==
'\0')) {
92 #if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN
95 ch = std::tolower(
ch);
99 bool IgnoreCase =
true) {
101 Key = convertToLowerCase(std::move(Key));
104 return Value.compare(0, Key.size(), Key) == 0;
108 void InitializeSystemInfo() {
109 #if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN
114 bool saw_mhz =
false;
123 ReadIntFromFile(
"/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)) {
126 cpuinfo_cycles_per_second = freq * 1000.0;
133 ReadIntFromFile(
"/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
137 cpuinfo_cycles_per_second = freq * 1000.0;
142 const char*
pname =
"/proc/cpuinfo";
143 int fd = open(
pname, O_RDONLY);
147 cpuinfo_cycles_per_second =
148 static_cast<double>(EstimateCyclesPerSecond());
153 double bogo_clock = 1.0;
154 bool saw_bogo =
false;
157 line[0] = line[1] =
'\0';
158 size_t chars_read = 0;
161 const size_t oldlinelen = strlen(line);
162 if (
sizeof(line) == oldlinelen + 1)
165 memmove(line, line + oldlinelen + 1,
sizeof(line) - (oldlinelen + 1));
167 char* newline = strchr(line,
'\n');
168 if (newline ==
nullptr) {
169 const size_t linelen = strlen(line);
170 const size_t bytes_to_read =
sizeof(line) - 1 - linelen;
171 CHECK(bytes_to_read > 0);
172 chars_read = read(fd, line + linelen, bytes_to_read);
173 line[linelen + chars_read] =
'\0';
174 newline = strchr(line,
'\n');
176 if (newline !=
nullptr) *newline =
'\0';
181 if (!saw_mhz && startsWithKey(line,
"cpu MHz")) {
182 const char* freqstr = strchr(line,
':');
184 cpuinfo_cycles_per_second = strtod(freqstr + 1, &
err) * 1000000.0;
185 if (freqstr[1] !=
'\0' && *
err ==
'\0' && cpuinfo_cycles_per_second > 0)
188 }
else if (startsWithKey(line,
"bogomips")) {
189 const char* freqstr = strchr(line,
':');
191 bogo_clock = strtod(freqstr + 1, &
err) * 1000000.0;
192 if (freqstr[1] !=
'\0' && *
err ==
'\0' && bogo_clock > 0)
195 }
else if (startsWithKey(line,
"processor",
false)) {
201 const char* id_str = strchr(line,
':');
203 const long cpu_id = strtol(id_str + 1, &
err, 10);
204 if (id_str[1] !=
'\0' && *
err ==
'\0' && max_cpu_id < cpu_id)
208 }
while (chars_read > 0);
215 cpuinfo_cycles_per_second = bogo_clock;
218 cpuinfo_cycles_per_second =
219 static_cast<double>(EstimateCyclesPerSecond());
223 fprintf(stderr,
"Failed to read num. CPUs correctly from /proc/cpuinfo\n");
225 if ((max_cpu_id + 1) != num_cpus) {
227 "CPU ID assignments in /proc/cpuinfo seem messed up."
228 " This is usually caused by a bad BIOS.\n");
230 cpuinfo_num_cpus = num_cpus;
233 #elif defined BENCHMARK_OS_FREEBSD
250 size_t sz =
sizeof(hz);
251 const char* sysctl_path =
"machdep.tsc_freq";
252 if (sysctlbyname(sysctl_path, &hz, &sz,
nullptr, 0) != 0) {
253 fprintf(stderr,
"Unable to determine clock rate from sysctl: %s: %s\n",
255 cpuinfo_cycles_per_second =
static_cast<double>(EstimateCyclesPerSecond());
257 cpuinfo_cycles_per_second = hz;
261 #elif defined BENCHMARK_OS_WINDOWS
264 DWORD
data, data_size =
sizeof(
data);
265 if (IsWindowsXPOrGreater() &&
267 SHGetValueA(HKEY_LOCAL_MACHINE,
268 "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
269 "~MHz",
nullptr, &
data, &data_size)))
270 cpuinfo_cycles_per_second =
271 static_cast<double>((int64_t)
data * (int64_t)(1000 * 1000));
273 cpuinfo_cycles_per_second =
static_cast<double>(EstimateCyclesPerSecond());
278 std::memset(&sysinfo, 0,
sizeof(SYSTEM_INFO));
279 GetSystemInfo(&sysinfo);
280 cpuinfo_num_cpus = sysinfo.dwNumberOfProcessors;
284 #elif defined BENCHMARK_OS_MACOSX
285 int32_t num_cpus = 0;
286 size_t size =
sizeof(num_cpus);
287 if (::sysctlbyname(
"hw.ncpu", &num_cpus, &
size,
nullptr, 0) == 0 &&
288 (
size ==
sizeof(num_cpus))) {
289 cpuinfo_num_cpus = num_cpus;
292 std::exit(EXIT_FAILURE);
294 int64_t cpu_freq = 0;
295 size =
sizeof(cpu_freq);
296 if (::sysctlbyname(
"hw.cpufrequency", &cpu_freq, &
size,
nullptr, 0) == 0 &&
297 (
size ==
sizeof(cpu_freq))) {
298 cpuinfo_cycles_per_second = cpu_freq;
300 #if defined BENCHMARK_OS_IOS
301 fprintf(stderr,
"CPU frequency cannot be detected. \n");
302 cpuinfo_cycles_per_second = 0;
305 std::exit(EXIT_FAILURE);
310 cpuinfo_cycles_per_second =
static_cast<double>(EstimateCyclesPerSecond());
318 return cpuinfo_cycles_per_second;
323 return cpuinfo_num_cpus;
327 #define strliterallen(str) (sizeof("" str "") - 1)
330 #define memprefix(str, len, prefix) \
331 ((((len) >= strliterallen(prefix)) && \
332 std::memcmp(str, prefix, strliterallen(prefix)) == 0) \
333 ? str + strliterallen(prefix) \
337 #ifndef BENCHMARK_OS_WINDOWS
341 for (
int cpu = 0, num_cpus =
NumCPUs(); cpu < num_cpus; ++cpu) {
343 StrCat(
"/sys/devices/system/cpu/cpu", cpu,
"/cpufreq/scaling_governor");
344 FILE* file = fopen(governor_file.c_str(),
"r");
347 size_t bytes_read = fread(buff, 1,
sizeof(buff), file);
349 if (
memprefix(buff, bytes_read,
"performance") ==
nullptr)
return true;