diff options
author | Henrik Edin <henrik.edin@mongodb.com> | 2018-12-06 13:38:31 -0500 |
---|---|---|
committer | Henrik Edin <henrik.edin@mongodb.com> | 2018-12-18 10:17:49 -0500 |
commit | b4df4609aa6951c503b2729f4e35d4a4d737cb0b (patch) | |
tree | 4b070ebab3f10e6fab4a5a5769d983b3cdc27523 /src | |
parent | 97fb988efa341f0a3e7bb9e250776352b4344c74 (diff) | |
download | mongo-b4df4609aa6951c503b2729f4e35d4a4d737cb0b.tar.gz |
SERVER-37994 Upgrade google benchmark to v1.4.1
Diffstat (limited to 'src')
-rw-r--r-- | src/third_party/SConscript | 2 | ||||
-rw-r--r-- | src/third_party/benchmark-1.3.0/benchmark/include/benchmark/benchmark_api.h | 27 | ||||
-rw-r--r-- | src/third_party/benchmark-1.3.0/benchmark/src/internal_macros.h | 57 | ||||
-rw-r--r-- | src/third_party/benchmark-1.3.0/benchmark/src/sysinfo.cc | 355 | ||||
-rw-r--r-- | src/third_party/benchmark-1.3.0/benchmark/src/sysinfo.h | 10 | ||||
-rw-r--r-- | src/third_party/benchmark-1.3.0/patches/0001-Use-STCK-to-get-the-CPU-clock-on-s390x.patch | 28 | ||||
-rw-r--r-- | src/third_party/benchmark-1.3.0/patches/0002-Work-around-MSVC-__forceinline-bug.patch | 27 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/SConscript (renamed from src/third_party/benchmark-1.3.0/SConscript) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/.gitignore (renamed from src/third_party/benchmark-1.3.0/benchmark/.gitignore) | 11 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/LICENSE (renamed from src/third_party/benchmark-1.3.0/benchmark/LICENSE) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/README.md (renamed from src/third_party/benchmark-1.3.0/benchmark/README.md) | 104 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/include/benchmark/benchmark.h (renamed from src/third_party/benchmark-1.3.0/benchmark/include/benchmark/benchmark.h) | 224 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/arraysize.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/arraysize.h) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/benchmark.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/src/benchmark.cc) | 180 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/benchmark_api_internal.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/benchmark_api_internal.h) | 2 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/benchmark_main.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/include/benchmark/reporter.h) | 16 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/benchmark_register.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/src/benchmark_register.cc) | 87 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/benchmark_register.h | 33 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/check.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/check.h) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/colorprint.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/src/colorprint.cc) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/colorprint.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/colorprint.h) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/commandlineflags.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/src/commandlineflags.cc) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/commandlineflags.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/commandlineflags.h) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/complexity.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/src/complexity.cc) | 22 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/complexity.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/complexity.h) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/console_reporter.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/src/console_reporter.cc) | 6 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/counter.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/src/counter.cc) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/counter.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/counter.h) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/csv_reporter.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/src/csv_reporter.cc) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/cycleclock.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/cycleclock.h) | 6 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/internal_macros.h | 89 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/json_reporter.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/src/json_reporter.cc) | 40 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/log.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/log.h) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/mutex.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/mutex.h) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/re.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/re.h) | 24 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/reporter.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/src/reporter.cc) | 28 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/sleep.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/src/sleep.cc) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/sleep.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/sleep.h) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/statistics.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/src/statistics.cc) | 25 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/statistics.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/statistics.h) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/string_util.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/src/string_util.cc) | 6 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/string_util.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/string_util.h) | 10 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/sysinfo.cc | 587 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/thread_manager.h | 66 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/thread_timer.h | 69 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/timers.cc (renamed from src/third_party/benchmark-1.3.0/benchmark/src/timers.cc) | 11 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/benchmark/src/timers.h (renamed from src/third_party/benchmark-1.3.0/benchmark/src/timers.h) | 0 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/patches/0001-Remove-deprecated-benchmark-fixture-function-decl.patch (renamed from src/third_party/benchmark-1.3.0/patches/0003-Remove-deprecated-benchmark-fixture-function-decl.patch) | 8 | ||||
-rw-r--r-- | src/third_party/benchmark-1.4.1/patches/0002-SERVER-33491-Fix-benchmark.h-compile-with-fdirective.patch | 30 | ||||
-rwxr-xr-x | src/third_party/scripts/benchmark_get_sources.sh | 39 |
50 files changed, 1382 insertions, 847 deletions
diff --git a/src/third_party/SConscript b/src/third_party/SConscript index 852d93235f2..990f779aff2 100644 --- a/src/third_party/SConscript +++ b/src/third_party/SConscript @@ -17,7 +17,7 @@ icuSuffix = '-57.1' gperftoolsSuffix = '-2.5' timelibSuffix = '-2018.01alpha1' tomcryptSuffix = '-1.18.1' -benchmarkSuffix = '-1.3.0' +benchmarkSuffix = '-1.4.1' sqliteSuffix = '-amalgamation-3190300' thirdPartyIncludePathList = [ diff --git a/src/third_party/benchmark-1.3.0/benchmark/include/benchmark/benchmark_api.h b/src/third_party/benchmark-1.3.0/benchmark/include/benchmark/benchmark_api.h deleted file mode 100644 index a9ae67147c5..00000000000 --- a/src/third_party/benchmark-1.3.0/benchmark/include/benchmark/benchmark_api.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef BENCHMARK_BENCHMARK_API_H_ -#define BENCHMARK_BENCHMARK_API_H_ - -#ifdef __DEPRECATED -# ifndef BENCHMARK_WARNING_MSG -# warning the benchmark_api.h header has been deprecated and will be removed, please include benchmark.h instead -# else - BENCHMARK_WARNING_MSG("the benchmark_api.h header has been deprecated and will be removed, please include benchmark.h instead") -# endif -#endif - -#include "benchmark.h" // For forward declaration of BenchmarkReporter - -#endif // BENCHMARK_BENCHMARK_API_H_ diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/internal_macros.h b/src/third_party/benchmark-1.3.0/benchmark/src/internal_macros.h deleted file mode 100644 index 942887457f1..00000000000 --- a/src/third_party/benchmark-1.3.0/benchmark/src/internal_macros.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef BENCHMARK_INTERNAL_MACROS_H_ -#define BENCHMARK_INTERNAL_MACROS_H_ - -#include "benchmark/benchmark.h" - -#ifndef __has_feature -#define __has_feature(x) 0 -#endif - -#if defined(__clang__) -#define COMPILER_CLANG -#elif defined(_MSC_VER) -#define COMPILER_MSVC -#elif defined(__GNUC__) -#define COMPILER_GCC -#endif - -#if __has_feature(cxx_attributes) -#define BENCHMARK_NORETURN [[noreturn]] -#elif defined(__GNUC__) -#define BENCHMARK_NORETURN __attribute__((noreturn)) -#elif defined(COMPILER_MSVC) -#define BENCHMARK_NORETURN __declspec(noreturn) -#else -#define BENCHMARK_NORETURN -#endif - -#if defined(__CYGWIN__) -#define BENCHMARK_OS_CYGWIN 1 -#elif defined(_WIN32) -#define BENCHMARK_OS_WINDOWS 1 -#elif defined(__APPLE__) -#include "TargetConditionals.h" - #if defined(TARGET_OS_MAC) - #define BENCHMARK_OS_MACOSX 1 - #if defined(TARGET_OS_IPHONE) - #define BENCHMARK_OS_IOS 1 - #endif - #endif -#elif defined(__FreeBSD__) -#define BENCHMARK_OS_FREEBSD 1 -#elif defined(__linux__) -#define BENCHMARK_OS_LINUX 1 -#elif defined(__native_client__) -#define BENCHMARK_OS_NACL 1 -#elif defined(EMSCRIPTEN) -#define BENCHMARK_OS_EMSCRIPTEN 1 -#elif defined(__rtems__) -#define BENCHMARK_OS_RTEMS 1 -#endif - -#if !__has_feature(cxx_exceptions) && !defined(__cpp_exceptions) \ - && !defined(__EXCEPTIONS) -#define BENCHMARK_HAS_NO_EXCEPTIONS -#endif - -#endif // BENCHMARK_INTERNAL_MACROS_H_ diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/sysinfo.cc b/src/third_party/benchmark-1.3.0/benchmark/src/sysinfo.cc deleted file mode 100644 index 7feb79e65f2..00000000000 --- a/src/third_party/benchmark-1.3.0/benchmark/src/sysinfo.cc +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "sysinfo.h" -#include "internal_macros.h" - -#ifdef BENCHMARK_OS_WINDOWS -#include <Shlwapi.h> -#include <VersionHelpers.h> -#include <Windows.h> -#else -#include <fcntl.h> -#include <sys/resource.h> -#include <sys/time.h> -#include <sys/types.h> // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD -#include <unistd.h> -#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX -#include <sys/sysctl.h> -#endif -#endif - -#include <cerrno> -#include <cstdint> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <iostream> -#include <limits> -#include <mutex> - -#include "arraysize.h" -#include "check.h" -#include "cycleclock.h" -#include "internal_macros.h" -#include "log.h" -#include "sleep.h" -#include "string_util.h" - -namespace benchmark { -namespace { -std::once_flag cpuinfo_init; -double cpuinfo_cycles_per_second = 1.0; -int cpuinfo_num_cpus = 1; // Conservative guess - -#if !defined BENCHMARK_OS_MACOSX -const int64_t estimate_time_ms = 1000; - -// Helper function estimates cycles/sec by observing cycles elapsed during -// sleep(). Using small sleep time decreases accuracy significantly. -int64_t EstimateCyclesPerSecond() { - const int64_t start_ticks = cycleclock::Now(); - SleepForMilliseconds(estimate_time_ms); - return cycleclock::Now() - start_ticks; -} -#endif - -#if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN -// Helper function for reading an int from a file. Returns true if successful -// and the memory location pointed to by value is set to the value read. -bool ReadIntFromFile(const char* file, long* value) { - bool ret = false; - int fd = open(file, O_RDONLY); - if (fd != -1) { - char line[1024]; - char* err; - memset(line, '\0', sizeof(line)); - ssize_t read_err = read(fd, line, sizeof(line) - 1); - ((void)read_err); // prevent unused warning - CHECK(read_err >= 0); - const long temp_value = strtol(line, &err, 10); - if (line[0] != '\0' && (*err == '\n' || *err == '\0')) { - *value = temp_value; - ret = true; - } - close(fd); - } - return ret; -} -#endif - -#if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN -static std::string convertToLowerCase(std::string s) { - for (auto& ch : s) - ch = std::tolower(ch); - return s; -} -static bool startsWithKey(std::string Value, std::string Key, - bool IgnoreCase = true) { - if (IgnoreCase) { - Key = convertToLowerCase(std::move(Key)); - Value = convertToLowerCase(std::move(Value)); - } - return Value.compare(0, Key.size(), Key) == 0; -} -#endif - -void InitializeSystemInfo() { -#if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN - char line[1024]; - char* err; - long freq; - - bool saw_mhz = false; - - // If the kernel is exporting the tsc frequency use that. There are issues - // where cpuinfo_max_freq cannot be relied on because the BIOS may be - // exporintg an invalid p-state (on x86) or p-states may be used to put the - // processor in a new mode (turbo mode). Essentially, those frequencies - // cannot always be relied upon. The same reasons apply to /proc/cpuinfo as - // well. - if (!saw_mhz && - ReadIntFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)) { - // The value is in kHz (as the file name suggests). For example, on a - // 2GHz warpstation, the file contains the value "2000000". - cpuinfo_cycles_per_second = freq * 1000.0; - saw_mhz = true; - } - - // If CPU scaling is in effect, we want to use the *maximum* frequency, - // not whatever CPU speed some random processor happens to be using now. - if (!saw_mhz && - ReadIntFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", - &freq)) { - // The value is in kHz. For example, on a 2GHz warpstation, the file - // contains the value "2000000". - cpuinfo_cycles_per_second = freq * 1000.0; - saw_mhz = true; - } - - // Read /proc/cpuinfo for other values, and if there is no cpuinfo_max_freq. - const char* pname = "/proc/cpuinfo"; - int fd = open(pname, O_RDONLY); - if (fd == -1) { - perror(pname); - if (!saw_mhz) { - cpuinfo_cycles_per_second = - static_cast<double>(EstimateCyclesPerSecond()); - } - return; - } - - double bogo_clock = 1.0; - bool saw_bogo = false; - long max_cpu_id = 0; - int num_cpus = 0; - line[0] = line[1] = '\0'; - size_t chars_read = 0; - do { // we'll exit when the last read didn't read anything - // Move the next line to the beginning of the buffer - const size_t oldlinelen = strlen(line); - if (sizeof(line) == oldlinelen + 1) // oldlinelen took up entire line - line[0] = '\0'; - else // still other lines left to save - memmove(line, line + oldlinelen + 1, sizeof(line) - (oldlinelen + 1)); - // Terminate the new line, reading more if we can't find the newline - char* newline = strchr(line, '\n'); - if (newline == nullptr) { - const size_t linelen = strlen(line); - const size_t bytes_to_read = sizeof(line) - 1 - linelen; - CHECK(bytes_to_read > 0); // because the memmove recovered >=1 bytes - chars_read = read(fd, line + linelen, bytes_to_read); - line[linelen + chars_read] = '\0'; - newline = strchr(line, '\n'); - } - if (newline != nullptr) *newline = '\0'; - - // When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only - // accept postive values. Some environments (virtual machines) report zero, - // which would cause infinite looping in WallTime_Init. - if (!saw_mhz && startsWithKey(line, "cpu MHz")) { - const char* freqstr = strchr(line, ':'); - if (freqstr) { - cpuinfo_cycles_per_second = strtod(freqstr + 1, &err) * 1000000.0; - if (freqstr[1] != '\0' && *err == '\0' && cpuinfo_cycles_per_second > 0) - saw_mhz = true; - } - } else if (startsWithKey(line, "bogomips")) { - const char* freqstr = strchr(line, ':'); - if (freqstr) { - bogo_clock = strtod(freqstr + 1, &err) * 1000000.0; - if (freqstr[1] != '\0' && *err == '\0' && bogo_clock > 0) - saw_bogo = true; - } - } else if (startsWithKey(line, "processor", /*IgnoreCase*/false)) { - // The above comparison is case-sensitive because ARM kernels often - // include a "Processor" line that tells you about the CPU, distinct - // from the usual "processor" lines that give you CPU ids. No current - // Linux architecture is using "Processor" for CPU ids. - num_cpus++; // count up every time we see an "processor :" entry - const char* id_str = strchr(line, ':'); - if (id_str) { - const long cpu_id = strtol(id_str + 1, &err, 10); - if (id_str[1] != '\0' && *err == '\0' && max_cpu_id < cpu_id) - max_cpu_id = cpu_id; - } - } - } while (chars_read > 0); - close(fd); - - if (!saw_mhz) { - if (saw_bogo) { - // If we didn't find anything better, we'll use bogomips, but - // we're not happy about it. - cpuinfo_cycles_per_second = bogo_clock; - } else { - // If we don't even have bogomips, we'll use the slow estimation. - cpuinfo_cycles_per_second = - static_cast<double>(EstimateCyclesPerSecond()); - } - } - if (num_cpus == 0) { - fprintf(stderr, "Failed to read num. CPUs correctly from /proc/cpuinfo\n"); - } else { - if ((max_cpu_id + 1) != num_cpus) { - fprintf(stderr, - "CPU ID assignments in /proc/cpuinfo seem messed up." - " This is usually caused by a bad BIOS.\n"); - } - cpuinfo_num_cpus = num_cpus; - } - -#elif defined BENCHMARK_OS_FREEBSD -// For this sysctl to work, the machine must be configured without -// SMP, APIC, or APM support. hz should be 64-bit in freebsd 7.0 -// and later. Before that, it's a 32-bit quantity (and gives the -// wrong answer on machines faster than 2^32 Hz). See -// http://lists.freebsd.org/pipermail/freebsd-i386/2004-November/001846.html -// But also compare FreeBSD 7.0: -// http://fxr.watson.org/fxr/source/i386/i386/tsc.c?v=RELENG70#L223 -// 231 error = sysctl_handle_quad(oidp, &freq, 0, req); -// To FreeBSD 6.3 (it's the same in 6-STABLE): -// http://fxr.watson.org/fxr/source/i386/i386/tsc.c?v=RELENG6#L131 -// 139 error = sysctl_handle_int(oidp, &freq, sizeof(freq), req); -#if __FreeBSD__ >= 7 - uint64_t hz = 0; -#else - unsigned int hz = 0; -#endif - size_t sz = sizeof(hz); - const char* sysctl_path = "machdep.tsc_freq"; - if (sysctlbyname(sysctl_path, &hz, &sz, nullptr, 0) != 0) { - fprintf(stderr, "Unable to determine clock rate from sysctl: %s: %s\n", - sysctl_path, strerror(errno)); - cpuinfo_cycles_per_second = static_cast<double>(EstimateCyclesPerSecond()); - } else { - cpuinfo_cycles_per_second = hz; - } -// TODO: also figure out cpuinfo_num_cpus - -#elif defined BENCHMARK_OS_WINDOWS - // In NT, read MHz from the registry. If we fail to do so or we're in win9x - // then make a crude estimate. - DWORD data, data_size = sizeof(data); - if (IsWindowsXPOrGreater() && - SUCCEEDED( - SHGetValueA(HKEY_LOCAL_MACHINE, - "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", - "~MHz", nullptr, &data, &data_size))) - cpuinfo_cycles_per_second = - static_cast<double>((int64_t)data * (int64_t)(1000 * 1000)); // was mhz - else - cpuinfo_cycles_per_second = static_cast<double>(EstimateCyclesPerSecond()); - - SYSTEM_INFO sysinfo; - // Use memset as opposed to = {} to avoid GCC missing initializer false - // positives. - std::memset(&sysinfo, 0, sizeof(SYSTEM_INFO)); - GetSystemInfo(&sysinfo); - cpuinfo_num_cpus = sysinfo.dwNumberOfProcessors; // number of logical - // processors in the current - // group - -#elif defined BENCHMARK_OS_MACOSX - int32_t num_cpus = 0; - size_t size = sizeof(num_cpus); - if (::sysctlbyname("hw.ncpu", &num_cpus, &size, nullptr, 0) == 0 && - (size == sizeof(num_cpus))) { - cpuinfo_num_cpus = num_cpus; - } else { - fprintf(stderr, "%s\n", strerror(errno)); - std::exit(EXIT_FAILURE); - } - int64_t cpu_freq = 0; - size = sizeof(cpu_freq); - if (::sysctlbyname("hw.cpufrequency", &cpu_freq, &size, nullptr, 0) == 0 && - (size == sizeof(cpu_freq))) { - cpuinfo_cycles_per_second = cpu_freq; - } else { - #if defined BENCHMARK_OS_IOS - fprintf(stderr, "CPU frequency cannot be detected. \n"); - cpuinfo_cycles_per_second = 0; - #else - fprintf(stderr, "%s\n", strerror(errno)); - std::exit(EXIT_FAILURE); - #endif - } -#else - // Generic cycles per second counter - cpuinfo_cycles_per_second = static_cast<double>(EstimateCyclesPerSecond()); -#endif -} - -} // end namespace - -double CyclesPerSecond(void) { - std::call_once(cpuinfo_init, InitializeSystemInfo); - return cpuinfo_cycles_per_second; -} - -int NumCPUs(void) { - std::call_once(cpuinfo_init, InitializeSystemInfo); - 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() { -#ifndef BENCHMARK_OS_WINDOWS - // 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; - } -#endif - return false; -} - -} // end namespace benchmark diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/sysinfo.h b/src/third_party/benchmark-1.3.0/benchmark/src/sysinfo.h deleted file mode 100644 index c5d9916d2dd..00000000000 --- a/src/third_party/benchmark-1.3.0/benchmark/src/sysinfo.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef BENCHMARK_SYSINFO_H_ -#define BENCHMARK_SYSINFO_H_ - -namespace benchmark { -int NumCPUs(); -double CyclesPerSecond(); -bool CpuScalingEnabled(); -} // end namespace benchmark - -#endif // BENCHMARK_SYSINFO_H_ diff --git a/src/third_party/benchmark-1.3.0/patches/0001-Use-STCK-to-get-the-CPU-clock-on-s390x.patch b/src/third_party/benchmark-1.3.0/patches/0001-Use-STCK-to-get-the-CPU-clock-on-s390x.patch deleted file mode 100644 index f1a06fbe0ae..00000000000 --- a/src/third_party/benchmark-1.3.0/patches/0001-Use-STCK-to-get-the-CPU-clock-on-s390x.patch +++ /dev/null @@ -1,28 +0,0 @@ -From f58107b74d08e604cac0fcec7bc3cf7a0e7a684f Mon Sep 17 00:00:00 2001 -From: Robert Guo <robert.guo@10gen.com> -Date: Fri, 19 Jan 2018 16:30:42 -0500 -Subject: [PATCH] Use STCK to get the CPU clock on s390x - ---- - src/cycleclock.h | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/cycleclock.h b/src/cycleclock.h -index 4251fe4..e8a5ae4 100644 ---- a/src/cycleclock.h -+++ b/src/cycleclock.h -@@ -159,6 +159,11 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { - struct timeval tv; - gettimeofday(&tv, nullptr); - return static_cast<int64_t>(tv.tv_sec) * 1000000 + tv.tv_usec; -+#elif defined(__s390__) -+ // MONGODB MODIFICATION: Return the CPU clock on s390x. -+ uint64_t tsc; -+ asm("\tstck\t%0\n" : "=Q" (tsc) : : "cc"); -+ return tsc; - #else - // The soft failover to a generic implementation is automatic only for ARM. - // For other platforms the developer is expected to make an attempt to create --- -2.14.3 (Apple Git-98) - diff --git a/src/third_party/benchmark-1.3.0/patches/0002-Work-around-MSVC-__forceinline-bug.patch b/src/third_party/benchmark-1.3.0/patches/0002-Work-around-MSVC-__forceinline-bug.patch deleted file mode 100644 index 4bbd33934b3..00000000000 --- a/src/third_party/benchmark-1.3.0/patches/0002-Work-around-MSVC-__forceinline-bug.patch +++ /dev/null @@ -1,27 +0,0 @@ -From df74ea738d9a797a2f5596c72ff08a2cd895168f Mon Sep 17 00:00:00 2001 -From: Robert Guo <robert.guo@10gen.com> -Date: Mon, 22 Jan 2018 18:19:04 -0500 -Subject: [PATCH] Work around MSVC __forceinline bug - ---- - include/benchmark/benchmark.h | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/include/benchmark/benchmark.h b/include/benchmark/benchmark.h -index d529e4b..f20787b 100644 ---- a/include/benchmark/benchmark.h -+++ b/include/benchmark/benchmark.h -@@ -207,7 +207,9 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); - #define BENCHMARK_NOEXCEPT_OP(x) noexcept(x) - #elif defined(_MSC_VER) && !defined(__clang__) - #define BENCHMARK_UNUSED --#define BENCHMARK_ALWAYS_INLINE __forceinline -+// MONGO HACK: SERVER-32908 work around old MSVC bug, which was fixed as of MSVC 1913. -+// See discussion here for more detail: https://github.com/google/benchmark/pull/493 -+#define BENCHMARK_ALWAYS_INLINE - #if _MSC_VER >= 1900 - #define BENCHMARK_NOEXCEPT noexcept - #define BENCHMARK_NOEXCEPT_OP(x) noexcept(x) --- -2.14.3 (Apple Git-98) - diff --git a/src/third_party/benchmark-1.3.0/SConscript b/src/third_party/benchmark-1.4.1/SConscript index 7e3b6e7487f..7e3b6e7487f 100644 --- a/src/third_party/benchmark-1.3.0/SConscript +++ b/src/third_party/benchmark-1.4.1/SConscript diff --git a/src/third_party/benchmark-1.3.0/benchmark/.gitignore b/src/third_party/benchmark-1.4.1/benchmark/.gitignore index 3c1b4f2183e..050e46987fa 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/.gitignore +++ b/src/third_party/benchmark-1.4.1/benchmark/.gitignore @@ -6,6 +6,7 @@ *.dylib *.cmake !/cmake/*.cmake +!/test/AssemblyTests.cmake *~ *.pyc __pycache__ @@ -41,6 +42,16 @@ build.ninja install_manifest.txt rules.ninja +# bazel output symlinks. +bazel-* + # out-of-source build top-level folders. build/ _build/ + +# in-source dependencies +/googletest/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +CMakeSettings.json diff --git a/src/third_party/benchmark-1.3.0/benchmark/LICENSE b/src/third_party/benchmark-1.4.1/benchmark/LICENSE index d6456956733..d6456956733 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/LICENSE +++ b/src/third_party/benchmark-1.4.1/benchmark/LICENSE diff --git a/src/third_party/benchmark-1.3.0/benchmark/README.md b/src/third_party/benchmark-1.4.1/benchmark/README.md index 67209090030..0341c31bd74 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/README.md +++ b/src/third_party/benchmark-1.4.1/benchmark/README.md @@ -2,6 +2,7 @@ [![Build Status](https://travis-ci.org/google/benchmark.svg?branch=master)](https://travis-ci.org/google/benchmark) [![Build status](https://ci.appveyor.com/api/projects/status/u0qsyp7t1tk7cpxs/branch/master?svg=true)](https://ci.appveyor.com/project/google/benchmark/branch/master) [![Coverage Status](https://coveralls.io/repos/google/benchmark/badge.svg)](https://coveralls.io/r/google/benchmark) +[![slackin](https://slackin-iqtfqnpzxd.now.sh/badge.svg)](https://slackin-iqtfqnpzxd.now.sh/) A library to support the benchmarking of functions, similar to unit-tests. @@ -13,6 +14,85 @@ IRC channel: https://freenode.net #googlebenchmark [Additional Tooling Documentation](docs/tools.md) +[Assembly Testing Documentation](docs/AssemblyTests.md) + + +## Building + +The basic steps for configuring and building the library look like this: + +```bash +$ git clone https://github.com/google/benchmark.git +# Benchmark requires Google Test as a dependency. Add the source tree as a subdirectory. +$ git clone https://github.com/google/googletest.git benchmark/googletest +$ mkdir build && cd build +$ cmake -G <generator> [options] ../benchmark +# Assuming a makefile generator was used +$ make +``` + +Note that Google Benchmark requires Google Test to build and run the tests. This +dependency can be provided two ways: + +* Checkout the Google Test sources into `benchmark/googletest` as above. +* Otherwise, if `-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON` is specified during + configuration, the library will automatically download and build any required + dependencies. + +If you do not wish to build and run the tests, add `-DBENCHMARK_ENABLE_GTEST_TESTS=OFF` +to `CMAKE_ARGS`. + + +## Installation Guide + +For Ubuntu and Debian Based System + +First make sure you have git and cmake installed (If not please install it) + +``` +sudo apt-get install git +sudo apt-get install cmake +``` + +Now, let's clone the repository and build it + +``` +git clone https://github.com/google/benchmark.git +cd benchmark +git clone https://github.com/google/googletest.git +mkdir build +cd build +cmake .. -DCMAKE_BUILD_TYPE=RELEASE +make +``` + +We need to install the library globally now + +``` +sudo make install +``` + +Now you have google/benchmark installed in your machine +Note: Don't forget to link to pthread library while building + +## Stable and Experimental Library Versions + +The main branch contains the latest stable version of the benchmarking library; +the API of which can be considered largely stable, with source breaking changes +being made only upon the release of a new major version. + +Newer, experimental, features are implemented and tested on the +[`v2` branch](https://github.com/google/benchmark/tree/v2). Users who wish +to use, test, and provide feedback on the new features are encouraged to try +this branch. However, this branch provides no stability guarantees and reserves +the right to change and break the API at any time. + +##Prerequisite knowledge + +Before attempting to understand this framework one should ideally have some familiarity with the structure and format of the Google Test framework, upon which it is based. Documentation for Google Test, including a "Getting Started" (primer) guide, is available here: +https://github.com/google/googletest/blob/master/googletest/docs/Documentation.md + + ## Example usage ### Basic usage Define a function that executes the code to be measured. @@ -38,7 +118,12 @@ BENCHMARK(BM_StringCopy); BENCHMARK_MAIN(); ``` -Don't forget to inform your linker to add benchmark library e.g. through `-lbenchmark` compilation flag. +Don't forget to inform your linker to add benchmark library e.g. through +`-lbenchmark` compilation flag. Alternatively, you may leave out the +`BENCHMARK_MAIN();` at the end of the source file and link against +`-lbenchmark_main` to get the same default behavior. + +The benchmark library will reporting the timing for the code within the `for(...)` loop. ### Passing arguments Sometimes a family of benchmarks can be implemented with just one routine that @@ -745,7 +830,7 @@ BM_SetInsert/1024/10 33157 33648 21431 1.13369M The JSON format outputs human readable json split into two top level attributes. The `context` attribute contains information about the run in general, including information about the CPU and the date. -The `benchmarks` attribute contains a list of ever benchmark run. Example json +The `benchmarks` attribute contains a list of every benchmark run. Example json output looks like: ```json { @@ -813,9 +898,15 @@ To enable link-time optimisation, use cmake -DCMAKE_BUILD_TYPE=Release -DBENCHMARK_ENABLE_LTO=true ``` +If you are using gcc, you might need to set `GCC_AR` and `GCC_RANLIB` cmake cache variables, if autodetection fails. +If you are using clang, you may need to set `LLVMAR_EXECUTABLE`, `LLVMNM_EXECUTABLE` and `LLVMRANLIB_EXECUTABLE` cmake cache variables. + ## Linking against the library -When using gcc, it is necessary to link against pthread to avoid runtime exceptions. -This is due to how gcc implements std::thread. + +When the library is built using GCC it is necessary to link with `-pthread`, +due to how GCC implements `std::thread`. + +For GCC 4.x failing to link to pthreads will lead to runtime exceptions, not linker errors. See [issue #67](https://github.com/google/benchmark/issues/67) for more details. ## Compiler Support @@ -849,8 +940,11 @@ sudo cpupower frequency-set --governor powersave # Known Issues -### Windows +### Windows with CMake * Users must manually link `shlwapi.lib`. Failure to do so may result in unresolved symbols. +### Solaris + +* Users must explicitly link with kstat library (-lkstat compilation flag). diff --git a/src/third_party/benchmark-1.3.0/benchmark/include/benchmark/benchmark.h b/src/third_party/benchmark-1.4.1/benchmark/include/benchmark/benchmark.h index 9529fafee18..23dd3d09b1f 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/include/benchmark/benchmark.h +++ b/src/third_party/benchmark-1.4.1/benchmark/include/benchmark/benchmark.h @@ -172,6 +172,7 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #include <stdint.h> +#include <algorithm> #include <cassert> #include <cstddef> #include <iosfwd> @@ -207,9 +208,7 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #define BENCHMARK_NOEXCEPT_OP(x) noexcept(x) #elif defined(_MSC_VER) && !defined(__clang__) #define BENCHMARK_UNUSED -// MONGO HACK: SERVER-32908 work around old MSVC bug, which was fixed as of MSVC 1913. -// See discussion here for more detail: https://github.com/google/benchmark/pull/493 -#define BENCHMARK_ALWAYS_INLINE +#define BENCHMARK_ALWAYS_INLINE __forceinline #if _MSC_VER >= 1900 #define BENCHMARK_NOEXCEPT noexcept #define BENCHMARK_NOEXCEPT_OP(x) noexcept(x) @@ -293,7 +292,7 @@ BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams(); #if (!defined(__GNUC__) && !defined(__clang__)) || defined(__pnacl__) || \ - defined(EMSCRIPTN) + defined(__EMSCRIPTEN__) # define BENCHMARK_HAS_NO_INLINE_ASSEMBLY #endif @@ -304,15 +303,20 @@ BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams(); // See: https://youtu.be/nXaxk27zwlk?t=2441 #ifndef BENCHMARK_HAS_NO_INLINE_ASSEMBLY template <class Tp> -inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { - // Clang doesn't like the 'X' constraint on `value` and certain GCC versions - // don't like the 'g' constraint. Attempt to placate them both. +inline BENCHMARK_ALWAYS_INLINE +void DoNotOptimize(Tp const& value) { + asm volatile("" : : "r,m"(value) : "memory"); +} + +template <class Tp> +inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) { #if defined(__clang__) - asm volatile("" : : "g"(value) : "memory"); + asm volatile("" : "+r,m"(value) : : "memory"); #else - asm volatile("" : : "i,r,m"(value) : "memory"); + asm volatile("" : "+m,r"(value) : : "memory"); #endif } + // Force the compiler to flush pending writes to global memory. Acts as an // effective read/write barrier inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() { @@ -381,7 +385,7 @@ enum BigO { oNone, o1, oN, oNSquared, oNCubed, oLogN, oNLogN, oAuto, oLambda }; // BigOFunc is passed to a benchmark in order to specify the asymptotic // computational complexity for the benchmark. -typedef double(BigOFunc)(int); +typedef double(BigOFunc)(int64_t); // StatisticsFunc is passed to a benchmark in order to compute some descriptive // statistics over all the measurements of some type @@ -431,16 +435,19 @@ class State { // Returns true if the benchmark should continue through another iteration. // NOTE: A benchmark may not return from the test until KeepRunning() has // returned false. - bool KeepRunning() { - if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) { - StartKeepRunning(); - } - bool const res = --total_iterations_; - if (BENCHMARK_BUILTIN_EXPECT(!res, false)) { - FinishKeepRunning(); - } - return res; - } + bool KeepRunning(); + + // Returns true iff the benchmark should run n more iterations. + // REQUIRES: 'n' > 0. + // NOTE: A benchmark must not return from the test until KeepRunningBatch() + // has returned false. + // NOTE: KeepRunningBatch() may overshoot by up to 'n' iterations. + // + // Intended usage: + // while (state.KeepRunningBatch(1000)) { + // // process 1000 elements + // } + bool KeepRunningBatch(size_t n); // REQUIRES: timer is running and 'SkipWithError(...)' has not been called // by the current thread. @@ -507,10 +514,10 @@ class State { // // REQUIRES: a benchmark has exited its benchmarking loop. BENCHMARK_ALWAYS_INLINE - void SetBytesProcessed(size_t bytes) { bytes_processed_ = bytes; } + void SetBytesProcessed(int64_t bytes) { bytes_processed_ = bytes; } BENCHMARK_ALWAYS_INLINE - size_t bytes_processed() const { return bytes_processed_; } + int64_t bytes_processed() const { return bytes_processed_; } // If this routine is called with complexity_n > 0 and complexity report is // requested for the @@ -518,10 +525,10 @@ class State { // and complexity_n will // represent the length of N. BENCHMARK_ALWAYS_INLINE - void SetComplexityN(int complexity_n) { complexity_n_ = complexity_n; } + void SetComplexityN(int64_t complexity_n) { complexity_n_ = complexity_n; } BENCHMARK_ALWAYS_INLINE - int complexity_length_n() { return complexity_n_; } + int64_t complexity_length_n() { return complexity_n_; } // If this routine is called with items > 0, then an items/s // label is printed on the benchmark report line for the currently @@ -530,10 +537,10 @@ class State { // // REQUIRES: a benchmark has exited its benchmarking loop. BENCHMARK_ALWAYS_INLINE - void SetItemsProcessed(size_t items) { items_processed_ = items; } + void SetItemsProcessed(int64_t items) { items_processed_ = items; } BENCHMARK_ALWAYS_INLINE - size_t items_processed() const { return items_processed_; } + int64_t items_processed() const { return items_processed_; } // If this routine is called, the specified label is printed at the // end of the benchmark report line for the currently executing @@ -541,7 +548,7 @@ class State { // static void BM_Compress(benchmark::State& state) { // ... // double compress = input_size / output_size; - // state.SetLabel(StringPrintf("compress:%.1f%%", 100.0*compression)); + // state.SetLabel(StrFormat("compress:%.1f%%", 100.0*compression)); // } // Produces output that looks like: // BM_Compress 50 50 14115038 compress:27.3% @@ -555,34 +562,52 @@ class State { // Range arguments for this run. CHECKs if the argument has been set. BENCHMARK_ALWAYS_INLINE - int range(std::size_t pos = 0) const { + int64_t range(std::size_t pos = 0) const { assert(range_.size() > pos); return range_[pos]; } BENCHMARK_DEPRECATED_MSG("use 'range(0)' instead") - int range_x() const { return range(0); } + int64_t range_x() const { return range(0); } BENCHMARK_DEPRECATED_MSG("use 'range(1)' instead") - int range_y() const { return range(1); } + int64_t range_y() const { return range(1); } BENCHMARK_ALWAYS_INLINE - size_t iterations() const { return (max_iterations - total_iterations_) + 1; } + size_t iterations() const { + if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) { + return 0; + } + return max_iterations - total_iterations_ + batch_leftover_; + } - private: - bool started_; - bool finished_; - size_t total_iterations_; +private: // items we expect on the first cache line (ie 64 bytes of the struct) - std::vector<int> range_; + // When total_iterations_ is 0, KeepRunning() and friends will return false. + // May be larger than max_iterations. + size_t total_iterations_; - size_t bytes_processed_; - size_t items_processed_; + // When using KeepRunningBatch(), batch_leftover_ holds the number of + // iterations beyond max_iters that were run. Used to track + // completed_iterations_ accurately. + size_t batch_leftover_; - int complexity_n_; +public: + const size_t max_iterations; +private: + bool started_; + bool finished_; bool error_occurred_; +private: // items we don't need on the first cache line + std::vector<int64_t> range_; + + int64_t bytes_processed_; + int64_t items_processed_; + + int64_t complexity_n_; + public: // Container for user-defined counters. UserCounters counters; @@ -590,27 +615,69 @@ class State { const int thread_index; // Number of threads concurrently executing the benchmark. const int threads; - const size_t max_iterations; + // TODO(EricWF) make me private - State(size_t max_iters, const std::vector<int>& ranges, int thread_i, + State(size_t max_iters, const std::vector<int64_t>& ranges, int thread_i, int n_threads, internal::ThreadTimer* timer, internal::ThreadManager* manager); private: void StartKeepRunning(); + // Implementation of KeepRunning() and KeepRunningBatch(). + // is_batch must be true unless n is 1. + bool KeepRunningInternal(size_t n, bool is_batch); void FinishKeepRunning(); internal::ThreadTimer* timer_; internal::ThreadManager* manager_; BENCHMARK_DISALLOW_COPY_AND_ASSIGN(State); }; +inline BENCHMARK_ALWAYS_INLINE +bool State::KeepRunning() { + return KeepRunningInternal(1, /*is_batch=*/ false); +} + +inline BENCHMARK_ALWAYS_INLINE +bool State::KeepRunningBatch(size_t n) { + return KeepRunningInternal(n, /*is_batch=*/ true); +} + +inline BENCHMARK_ALWAYS_INLINE +bool State::KeepRunningInternal(size_t n, bool is_batch) { + // total_iterations_ is set to 0 by the constructor, and always set to a + // nonzero value by StartKepRunning(). + assert(n > 0); + // n must be 1 unless is_batch is true. + assert(is_batch || n == 1); + if (BENCHMARK_BUILTIN_EXPECT(total_iterations_ >= n, true)) { + total_iterations_ -= n; + return true; + } + if (!started_) { + StartKeepRunning(); + if (!error_occurred_ && total_iterations_ >= n) { + total_iterations_-= n; + return true; + } + } + // For non-batch runs, total_iterations_ must be 0 by now. + if (is_batch && total_iterations_ != 0) { + batch_leftover_ = n - total_iterations_; + total_iterations_ = 0; + return true; + } + FinishKeepRunning(); + return false; +} + struct State::StateIterator { struct BENCHMARK_UNUSED Value {}; typedef std::forward_iterator_tag iterator_category; typedef Value value_type; typedef Value reference; typedef Value pointer; + typedef std::ptrdiff_t difference_type; private: friend class State; @@ -644,10 +711,10 @@ struct State::StateIterator { State* const parent_; }; -BENCHMARK_ALWAYS_INLINE inline State::StateIterator State::begin() { +inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::begin() { return StateIterator(this); } -BENCHMARK_ALWAYS_INLINE inline State::StateIterator State::end() { +inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::end() { StartKeepRunning(); return StateIterator(); } @@ -672,7 +739,7 @@ class Benchmark { // Run this benchmark once with "x" as the extra argument passed // to the function. // REQUIRES: The function passed to the constructor must accept an arg1. - Benchmark* Arg(int x); + Benchmark* Arg(int64_t x); // Run this benchmark with the given time unit for the generated output report Benchmark* Unit(TimeUnit unit); @@ -680,23 +747,23 @@ class Benchmark { // Run this benchmark once for a number of values picked from the // range [start..limit]. (start and limit are always picked.) // REQUIRES: The function passed to the constructor must accept an arg1. - Benchmark* Range(int start, int limit); + Benchmark* Range(int64_t start, int64_t limit); // Run this benchmark once for all values in the range [start..limit] with // specific step // REQUIRES: The function passed to the constructor must accept an arg1. - Benchmark* DenseRange(int start, int limit, int step = 1); + Benchmark* DenseRange(int64_t start, int64_t limit, int step = 1); // Run this benchmark once with "args" as the extra arguments passed // to the function. // REQUIRES: The function passed to the constructor must accept arg1, arg2 ... - Benchmark* Args(const std::vector<int>& args); + Benchmark* Args(const std::vector<int64_t>& args); // Equivalent to Args({x, y}) // NOTE: This is a legacy C++03 interface provided for compatibility only. // New code should use 'Args'. - Benchmark* ArgPair(int x, int y) { - std::vector<int> args; + Benchmark* ArgPair(int64_t x, int64_t y) { + std::vector<int64_t> args; args.push_back(x); args.push_back(y); return Args(args); @@ -705,7 +772,7 @@ class Benchmark { // Run this benchmark once for a number of values picked from the // ranges [start..limit]. (starts and limits are always picked.) // REQUIRES: The function passed to the constructor must accept arg1, arg2 ... - Benchmark* Ranges(const std::vector<std::pair<int, int> >& ranges); + Benchmark* Ranges(const std::vector<std::pair<int64_t, int64_t> >& ranges); // Equivalent to ArgNames({name}) Benchmark* ArgName(const std::string& name); @@ -717,8 +784,8 @@ class Benchmark { // Equivalent to Ranges({{lo1, hi1}, {lo2, hi2}}). // NOTE: This is a legacy C++03 interface provided for compatibility only. // New code should use 'Ranges'. - Benchmark* RangePair(int lo1, int hi1, int lo2, int hi2) { - std::vector<std::pair<int, int> > ranges; + Benchmark* RangePair(int64_t lo1, int64_t hi1, int64_t lo2, int64_t hi2) { + std::vector<std::pair<int64_t, int64_t> > ranges; ranges.push_back(std::make_pair(lo1, hi1)); ranges.push_back(std::make_pair(lo2, hi2)); return Ranges(ranges); @@ -825,15 +892,13 @@ class Benchmark { int ArgsCnt() const; - static void AddRange(std::vector<int>* dst, int lo, int hi, int mult); - private: friend class BenchmarkFamilies; std::string name_; ReportMode report_mode_; std::vector<std::string> arg_names_; // Args for all benchmark runs - std::vector<std::vector<int> > args_; // Args for all benchmark runs + std::vector<std::vector<int64_t> > args_; // Args for all benchmark runs TimeUnit time_unit_; int range_multiplier_; double min_time_; @@ -943,10 +1008,12 @@ class Fixture : public internal::Benchmark { this->TearDown(st); } - // MONGODB MODIFICATION: Remove the deprecated version of SetUp() and TearDown() that - // require `const State&` as an argument. - virtual void SetUp(State&) {} - virtual void TearDown(State&) {} + // These will be deprecated ... + virtual void SetUp(const State&) {} + virtual void TearDown(const State&) {} + // ... In favor of these. + virtual void SetUp(State& st) { SetUp(const_cast<const State&>(st)); } + virtual void TearDown(State& st) { TearDown(const_cast<const State&>(st)); } protected: virtual void BenchmarkCase(State&) = 0; @@ -960,12 +1027,7 @@ class Fixture : public internal::Benchmark { // Check that __COUNTER__ is defined and that __COUNTER__ increases by 1 // every time it is expanded. X + 1 == X + 0 is used in case X is defined to be // empty. If X is empty the expression becomes (+1 == +0). -// -// MONGODB MODIFICATION: all of our supported compilers support __COUNTER__ so we don't need to test -// for it here. This test interferes with -E -fdirectives-only since it is illegal to use -// __COUNTER__ in an #if clause with that flag because its value could change between the partial -// preprocessing and the compile phases. -#if true // defined(__COUNTER__) && (__COUNTER__ + 1 == __COUNTER__ + 0) +#if defined(__COUNTER__) && (__COUNTER__ + 1 == __COUNTER__ + 0) #define BENCHMARK_PRIVATE_UNIQUE_ID __COUNTER__ #else #define BENCHMARK_PRIVATE_UNIQUE_ID __LINE__ @@ -1151,7 +1213,8 @@ class Fixture : public internal::Benchmark { ::benchmark::Initialize(&argc, argv); \ if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; \ ::benchmark::RunSpecifiedBenchmarks(); \ - } + } \ + int main(int, char**) // ------------------------------------------------------ @@ -1159,6 +1222,26 @@ class Fixture : public internal::Benchmark { namespace benchmark { +struct CPUInfo { + struct CacheInfo { + std::string type; + int level; + int size; + int num_sharing; + }; + + int num_cpus; + double cycles_per_second; + std::vector<CacheInfo> caches; + bool scaling_enabled; + + static const CPUInfo& Get(); + + private: + CPUInfo(); + BENCHMARK_DISALLOW_COPY_AND_ASSIGN(CPUInfo); +}; + // Interface for custom benchmark result printers. // By default, benchmark reports are printed to stdout. However an application // can control the destination of the reports by calling @@ -1167,12 +1250,11 @@ namespace benchmark { class BenchmarkReporter { public: struct Context { - int num_cpus; - double mhz_per_cpu; - bool cpu_scaling_enabled; - + CPUInfo const& cpu_info; // The number of chars in the longest benchmark name. size_t name_field_width; + static const char *executable_name; + Context(); }; struct Run { @@ -1224,7 +1306,7 @@ class BenchmarkReporter { // Keep track of arguments to compute asymptotic complexity BigO complexity; BigOFunc* complexity_lambda; - int complexity_n; + int64_t complexity_n; // what statistics to compute from the measurements const std::vector<Statistics>* statistics; diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/arraysize.h b/src/third_party/benchmark-1.4.1/benchmark/src/arraysize.h index 51a50f2dff2..51a50f2dff2 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/arraysize.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/arraysize.h diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/benchmark.cc b/src/third_party/benchmark-1.4.1/benchmark/src/benchmark.cc index a72ac470e5b..82b15ac7090 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/benchmark.cc +++ b/src/third_party/benchmark-1.4.1/benchmark/src/benchmark.cc @@ -17,7 +17,9 @@ #include "internal_macros.h" #ifndef BENCHMARK_OS_WINDOWS +#ifndef BENCHMARK_OS_FUCHSIA #include <sys/resource.h> +#endif #include <sys/time.h> #include <unistd.h> #endif @@ -27,24 +29,25 @@ #include <condition_variable> #include <cstdio> #include <cstdlib> -#include <cstring> #include <fstream> #include <iostream> #include <memory> +#include <string> #include <thread> #include "check.h" #include "colorprint.h" #include "commandlineflags.h" #include "complexity.h" -#include "statistics.h" #include "counter.h" +#include "internal_macros.h" #include "log.h" #include "mutex.h" #include "re.h" +#include "statistics.h" #include "string_util.h" -#include "sysinfo.h" -#include "timers.h" +#include "thread_manager.h" +#include "thread_timer.h" DEFINE_bool(benchmark_list_tests, false, "Print a list of benchmarks. This option overrides all other " @@ -82,7 +85,7 @@ DEFINE_string(benchmark_out_format, "json", "The format to use for file output. Valid values are " "'console', 'json', or 'csv'."); -DEFINE_string(benchmark_out, "", "The file to write additonal output to"); +DEFINE_string(benchmark_out, "", "The file to write additional output to"); DEFINE_string(benchmark_color, "auto", "Whether to use colors in the output. Valid values: " @@ -108,116 +111,11 @@ namespace internal { void UseCharPointer(char const volatile*) {} -class ThreadManager { - public: - ThreadManager(int num_threads) - : alive_threads_(num_threads), start_stop_barrier_(num_threads) {} - - Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) { - return benchmark_mutex_; - } - - bool StartStopBarrier() EXCLUDES(end_cond_mutex_) { - return start_stop_barrier_.wait(); - } - - void NotifyThreadComplete() EXCLUDES(end_cond_mutex_) { - start_stop_barrier_.removeThread(); - if (--alive_threads_ == 0) { - MutexLock lock(end_cond_mutex_); - end_condition_.notify_all(); - } - } - - void WaitForAllThreads() EXCLUDES(end_cond_mutex_) { - MutexLock lock(end_cond_mutex_); - end_condition_.wait(lock.native_handle(), - [this]() { return alive_threads_ == 0; }); - } - - public: - struct Result { - double real_time_used = 0; - double cpu_time_used = 0; - double manual_time_used = 0; - int64_t bytes_processed = 0; - int64_t items_processed = 0; - int complexity_n = 0; - std::string report_label_; - std::string error_message_; - bool has_error_ = false; - UserCounters counters; - }; - GUARDED_BY(GetBenchmarkMutex()) Result results; - - private: - mutable Mutex benchmark_mutex_; - std::atomic<int> alive_threads_; - Barrier start_stop_barrier_; - Mutex end_cond_mutex_; - Condition end_condition_; -}; - -// Timer management class -class ThreadTimer { - public: - ThreadTimer() = default; - - // Called by each thread - void StartTimer() { - running_ = true; - start_real_time_ = ChronoClockNow(); - start_cpu_time_ = ThreadCPUUsage(); - } - - // Called by each thread - void StopTimer() { - CHECK(running_); - running_ = false; - real_time_used_ += ChronoClockNow() - start_real_time_; - cpu_time_used_ += ThreadCPUUsage() - start_cpu_time_; - } - - // Called by each thread - void SetIterationTime(double seconds) { manual_time_used_ += seconds; } - - bool running() const { return running_; } - - // REQUIRES: timer is not running - double real_time_used() { - CHECK(!running_); - return real_time_used_; - } - - // REQUIRES: timer is not running - double cpu_time_used() { - CHECK(!running_); - return cpu_time_used_; - } - - // REQUIRES: timer is not running - double manual_time_used() { - CHECK(!running_); - return manual_time_used_; - } - - private: - bool running_ = false; // Is the timer running - double start_real_time_ = 0; // If running_ - double start_cpu_time_ = 0; // If running_ - - // Accumulated time so far (does not contain current slice if running_) - double real_time_used_ = 0; - double cpu_time_used_ = 0; - // Manually set iteration time. User sets this with SetIterationTime(seconds). - double manual_time_used_ = 0; -}; - namespace { BenchmarkReporter::Run CreateRunReport( const benchmark::internal::Benchmark::Instance& b, - const internal::ThreadManager::Result& results, size_t iters, + const internal::ThreadManager::Result& results, double seconds) { // Create report about this benchmark run. BenchmarkReporter::Run report; @@ -226,8 +124,8 @@ BenchmarkReporter::Run CreateRunReport( report.error_occurred = results.has_error_; report.error_message = results.error_message_; report.report_label = results.report_label_; - // Report the total iterations across all threads. - report.iterations = static_cast<int64_t>(iters) * b.threads; + // This is the total iterations across all threads. + report.iterations = results.iterations; report.time_unit = b.time_unit; if (!report.error_occurred) { @@ -266,11 +164,12 @@ void RunInThread(const benchmark::internal::Benchmark::Instance* b, internal::ThreadTimer timer; State st(iters, b->arg, thread_id, b->threads, &timer, manager); b->benchmark->Run(st); - CHECK(st.iterations() == st.max_iterations) + CHECK(st.iterations() >= st.max_iterations) << "Benchmark returned before State::KeepRunning() returned false!"; { MutexLock l(manager->GetBenchmarkMutex()); internal::ThreadManager::Result& results = manager->results; + results.iterations += st.iterations(); results.cpu_time_used += timer.cpu_time_used(); results.real_time_used += timer.real_time_used(); results.manual_time_used += timer.manual_time_used(); @@ -338,18 +237,17 @@ std::vector<BenchmarkReporter::Run> RunBenchmark( // Determine if this run should be reported; Either it has // run for a sufficient amount of time or because an error was reported. const bool should_report = repetition_num > 0 - || has_explicit_iteration_count // An exact iteration count was requested + || has_explicit_iteration_count // An exact iteration count was requested || results.has_error_ - || iters >= kMaxIterations - || seconds >= min_time // the elapsed time is large enough + || iters >= kMaxIterations // No chance to try again, we hit the limit. + || seconds >= min_time // the elapsed time is large enough // CPU time is specified but the elapsed real time greatly exceeds the // minimum time. Note that user provided timers are except from this // sanity check. || ((results.real_time_used >= 5 * min_time) && !b.use_manual_time); if (should_report) { - BenchmarkReporter::Run report = - CreateRunReport(b, results, iters, seconds); + BenchmarkReporter::Run report = CreateRunReport(b, results, seconds); if (!report.error_occurred && b.complexity != oNone) complexity_reports->push_back(report); reports.push_back(report); @@ -392,26 +290,44 @@ std::vector<BenchmarkReporter::Run> RunBenchmark( } // namespace } // namespace internal -State::State(size_t max_iters, const std::vector<int>& ranges, int thread_i, +State::State(size_t max_iters, const std::vector<int64_t>& ranges, int thread_i, int n_threads, internal::ThreadTimer* timer, internal::ThreadManager* manager) - : started_(false), + : total_iterations_(0), + batch_leftover_(0), + max_iterations(max_iters), + started_(false), finished_(false), - total_iterations_(max_iters + 1), + error_occurred_(false), range_(ranges), bytes_processed_(0), items_processed_(0), complexity_n_(0), - error_occurred_(false), counters(), thread_index(thread_i), threads(n_threads), - max_iterations(max_iters), timer_(timer), manager_(manager) { CHECK(max_iterations != 0) << "At least one iteration must be run"; - CHECK(total_iterations_ != 0) << "max iterations wrapped around"; CHECK_LT(thread_index, threads) << "thread_index must be less than threads"; + + // Note: The use of offsetof below is technically undefined until C++17 + // because State is not a standard layout type. However, all compilers + // currently provide well-defined behavior as an extension (which is + // demonstrated since constexpr evaluation must diagnose all undefined + // behavior). However, GCC and Clang also warn about this use of offsetof, + // which must be suppressed. +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winvalid-offsetof" +#endif + // Offset tests to ensure commonly accessed data is on the first cache line. + const int cache_line_size = 64; + static_assert(offsetof(State, error_occurred_) <= + (cache_line_size - sizeof(error_occurred_)), ""); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif } void State::PauseTiming() { @@ -435,7 +351,7 @@ void State::SkipWithError(const char* msg) { manager_->results.has_error_ = true; } } - total_iterations_ = 1; + total_iterations_ = 0; if (timer_->running()) timer_->StopTimer(); } @@ -451,6 +367,7 @@ void State::SetLabel(const char* label) { void State::StartKeepRunning() { CHECK(!started_ && !finished_); started_ = true; + total_iterations_ = error_occurred_ ? 0 : max_iterations; manager_->StartStopBarrier(); if (!error_occurred_) ResumeTiming(); } @@ -460,8 +377,8 @@ void State::FinishKeepRunning() { if (!error_occurred_) { PauseTiming(); } - // Total iterations has now wrapped around zero. Fix this. - total_iterations_ = 1; + // Total iterations has now wrapped around past 0. Fix this. + total_iterations_ = 0; finished_ = true; manager_->StartStopBarrier(); } @@ -491,13 +408,9 @@ void RunBenchmarks(const std::vector<Benchmark::Instance>& benchmarks, // Print header here BenchmarkReporter::Context context; - context.num_cpus = NumCPUs(); - context.mhz_per_cpu = CyclesPerSecond() / 1000000.0; - - context.cpu_scaling_enabled = CpuScalingEnabled(); context.name_field_width = name_field_width; - // Keep track of runing times of all instances of current benchmark + // Keep track of running times of all instances of current benchmark std::vector<BenchmarkReporter::Run> complexity_reports; // We flush streams after invoking reporter methods that write to them. This @@ -655,6 +568,7 @@ void PrintUsageAndExit() { void ParseCommandLineFlags(int* argc, char** argv) { using namespace benchmark; + BenchmarkReporter::Context::executable_name = argv[0]; for (int i = 1; i < *argc; ++i) { if (ParseBoolFlag(argv[i], "benchmark_list_tests", &FLAGS_benchmark_list_tests) || diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/benchmark_api_internal.h b/src/third_party/benchmark-1.4.1/benchmark/src/benchmark_api_internal.h index d481dc52864..dd7a3ffe8cb 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/benchmark_api_internal.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/benchmark_api_internal.h @@ -17,7 +17,7 @@ struct Benchmark::Instance { std::string name; Benchmark* benchmark; ReportMode report_mode; - std::vector<int> arg; + std::vector<int64_t> arg; TimeUnit time_unit; int range_multiplier; bool use_real_time; diff --git a/src/third_party/benchmark-1.3.0/benchmark/include/benchmark/reporter.h b/src/third_party/benchmark-1.4.1/benchmark/src/benchmark_main.cc index 5baca1a740a..b3b24783149 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/include/benchmark/reporter.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/benchmark_main.cc @@ -1,4 +1,4 @@ -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2018 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,17 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -#ifndef BENCHMARK_REPORTER_H_ -#define BENCHMARK_REPORTER_H_ -#ifdef __DEPRECATED -# ifndef BENCHMARK_WARNING_MSG -# warning the reporter.h header has been deprecated and will be removed, please include benchmark.h instead -# else - BENCHMARK_WARNING_MSG("the reporter.h header has been deprecated and will be removed, please include benchmark.h instead") -# endif -#endif +#include "benchmark/benchmark.h" -#include "benchmark.h" // For forward declaration of BenchmarkReporter - -#endif // BENCHMARK_REPORTER_H_ +BENCHMARK_MAIN(); diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/benchmark_register.cc b/src/third_party/benchmark-1.4.1/benchmark/src/benchmark_register.cc index c1b80674839..dc6f9356853 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/benchmark_register.cc +++ b/src/third_party/benchmark-1.4.1/benchmark/src/benchmark_register.cc @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "benchmark/benchmark.h" -#include "benchmark_api_internal.h" -#include "internal_macros.h" +#include "benchmark_register.h" #ifndef BENCHMARK_OS_WINDOWS +#ifndef BENCHMARK_OS_FUCHSIA #include <sys/resource.h> +#endif #include <sys/time.h> #include <unistd.h> #endif @@ -34,15 +34,17 @@ #include <sstream> #include <thread> +#include "benchmark/benchmark.h" +#include "benchmark_api_internal.h" #include "check.h" #include "commandlineflags.h" #include "complexity.h" -#include "statistics.h" +#include "internal_macros.h" #include "log.h" #include "mutex.h" #include "re.h" +#include "statistics.h" #include "string_util.h" -#include "sysinfo.h" #include "timers.h" namespace benchmark { @@ -75,7 +77,7 @@ class BenchmarkFamilies { // Extract the list of benchmark instances that match the specified // regular expression. - bool FindBenchmarks(const std::string& re, + bool FindBenchmarks(std::string re, std::vector<Benchmark::Instance>* benchmarks, std::ostream* Err); @@ -105,13 +107,18 @@ void BenchmarkFamilies::ClearBenchmarks() { } bool BenchmarkFamilies::FindBenchmarks( - const std::string& spec, std::vector<Benchmark::Instance>* benchmarks, + std::string spec, std::vector<Benchmark::Instance>* benchmarks, std::ostream* ErrStream) { CHECK(ErrStream); auto& Err = *ErrStream; // Make regular expression out of command-line flag std::string error_msg; Regex re; + bool isNegativeFilter = false; + if(spec[0] == '-') { + spec.replace(0, 1, ""); + isNegativeFilter = true; + } if (!re.Init(spec, &error_msg)) { Err << "Could not compile benchmark re: " << error_msg << std::endl; return false; @@ -171,20 +178,20 @@ bool BenchmarkFamilies::FindBenchmarks( const auto& arg_name = family->arg_names_[arg_i]; if (!arg_name.empty()) { instance.name += - StringPrintF("%s:", family->arg_names_[arg_i].c_str()); + StrFormat("%s:", family->arg_names_[arg_i].c_str()); } } - - instance.name += StringPrintF("%d", arg); + + instance.name += StrFormat("%d", arg); ++arg_i; } if (!IsZero(family->min_time_)) - instance.name += StringPrintF("/min_time:%0.3f", family->min_time_); + instance.name += StrFormat("/min_time:%0.3f", family->min_time_); if (family->iterations_ != 0) - instance.name += StringPrintF("/iterations:%d", family->iterations_); + instance.name += StrFormat("/iterations:%d", family->iterations_); if (family->repetitions_ != 0) - instance.name += StringPrintF("/repeats:%d", family->repetitions_); + instance.name += StrFormat("/repeats:%d", family->repetitions_); if (family->use_manual_time_) { instance.name += "/manual_time"; @@ -194,10 +201,11 @@ bool BenchmarkFamilies::FindBenchmarks( // Add the number of threads used to the name if (!family->thread_counts_.empty()) { - instance.name += StringPrintF("/threads:%d", instance.threads); + instance.name += StrFormat("/threads:%d", instance.threads); } - if (re.Match(instance.name)) { + if ((re.Match(instance.name) && !isNegativeFilter) || + (!re.Match(instance.name) && isNegativeFilter)) { instance.last_benchmark_instance = (&args == &family->args_.back()); benchmarks->push_back(std::move(instance)); } @@ -245,30 +253,7 @@ Benchmark::Benchmark(const char* name) Benchmark::~Benchmark() {} -void Benchmark::AddRange(std::vector<int>* dst, int lo, int hi, int mult) { - CHECK_GE(lo, 0); - CHECK_GE(hi, lo); - CHECK_GE(mult, 2); - - // Add "lo" - dst->push_back(lo); - - static const int kint32max = std::numeric_limits<int32_t>::max(); - - // Now space out the benchmarks in multiples of "mult" - for (int32_t i = 1; i < kint32max / mult; i *= mult) { - if (i >= hi) break; - if (i > lo) { - dst->push_back(i); - } - } - // Add "hi" (if different from "lo") - if (hi != lo) { - dst->push_back(hi); - } -} - -Benchmark* Benchmark::Arg(int x) { +Benchmark* Benchmark::Arg(int64_t x) { CHECK(ArgsCnt() == -1 || ArgsCnt() == 1); args_.push_back({x}); return this; @@ -279,20 +264,21 @@ Benchmark* Benchmark::Unit(TimeUnit unit) { return this; } -Benchmark* Benchmark::Range(int start, int limit) { +Benchmark* Benchmark::Range(int64_t start, int64_t limit) { CHECK(ArgsCnt() == -1 || ArgsCnt() == 1); - std::vector<int> arglist; + std::vector<int64_t> arglist; AddRange(&arglist, start, limit, range_multiplier_); - for (int i : arglist) { + for (int64_t i : arglist) { args_.push_back({i}); } return this; } -Benchmark* Benchmark::Ranges(const std::vector<std::pair<int, int>>& ranges) { +Benchmark* Benchmark::Ranges( + const std::vector<std::pair<int64_t, int64_t>>& ranges) { CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(ranges.size())); - std::vector<std::vector<int>> arglists(ranges.size()); + std::vector<std::vector<int64_t>> arglists(ranges.size()); std::size_t total = 1; for (std::size_t i = 0; i < ranges.size(); i++) { AddRange(&arglists[i], ranges[i].first, ranges[i].second, @@ -303,7 +289,7 @@ Benchmark* Benchmark::Ranges(const std::vector<std::pair<int, int>>& ranges) { std::vector<std::size_t> ctr(arglists.size(), 0); for (std::size_t i = 0; i < total; i++) { - std::vector<int> tmp; + std::vector<int64_t> tmp; tmp.reserve(arglists.size()); for (std::size_t j = 0; j < arglists.size(); j++) { @@ -335,17 +321,17 @@ Benchmark* Benchmark::ArgNames(const std::vector<std::string>& names) { return this; } -Benchmark* Benchmark::DenseRange(int start, int limit, int step) { +Benchmark* Benchmark::DenseRange(int64_t start, int64_t limit, int step) { CHECK(ArgsCnt() == -1 || ArgsCnt() == 1); CHECK_GE(start, 0); CHECK_LE(start, limit); - for (int arg = start; arg <= limit; arg += step) { + for (int64_t arg = start; arg <= limit; arg += step) { args_.push_back({arg}); } return this; } -Benchmark* Benchmark::Args(const std::vector<int>& args) { +Benchmark* Benchmark::Args(const std::vector<int64_t>& args) { CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(args.size())); args_.push_back(args); return this; @@ -362,7 +348,6 @@ Benchmark* Benchmark::RangeMultiplier(int multiplier) { return this; } - Benchmark* Benchmark::MinTime(double t) { CHECK(t > 0.0); CHECK(iterations_ == 0); @@ -370,7 +355,6 @@ Benchmark* Benchmark::MinTime(double t) { return this; } - Benchmark* Benchmark::Iterations(size_t n) { CHECK(n > 0); CHECK(IsZero(min_time_)); @@ -448,8 +432,7 @@ Benchmark* Benchmark::DenseThreadRange(int min_threads, int max_threads, } Benchmark* Benchmark::ThreadPerCpu() { - static int num_cpus = NumCPUs(); - thread_counts_.push_back(num_cpus); + thread_counts_.push_back(CPUInfo::Get().num_cpus); return this; } diff --git a/src/third_party/benchmark-1.4.1/benchmark/src/benchmark_register.h b/src/third_party/benchmark-1.4.1/benchmark/src/benchmark_register.h new file mode 100644 index 00000000000..0705e219f2f --- /dev/null +++ b/src/third_party/benchmark-1.4.1/benchmark/src/benchmark_register.h @@ -0,0 +1,33 @@ +#ifndef BENCHMARK_REGISTER_H +#define BENCHMARK_REGISTER_H + +#include <vector> + +#include "check.h" + +template <typename T> +void AddRange(std::vector<T>* dst, T lo, T hi, int mult) { + CHECK_GE(lo, 0); + CHECK_GE(hi, lo); + CHECK_GE(mult, 2); + + // Add "lo" + dst->push_back(lo); + + static const T kmax = std::numeric_limits<T>::max(); + + // Now space out the benchmarks in multiples of "mult" + for (T i = 1; i < kmax / mult; i *= mult) { + if (i >= hi) break; + if (i > lo) { + dst->push_back(i); + } + } + + // Add "hi" (if different from "lo") + if (hi != lo) { + dst->push_back(hi); + } +} + +#endif // BENCHMARK_REGISTER_H diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/check.h b/src/third_party/benchmark-1.4.1/benchmark/src/check.h index 73bead2fb55..73bead2fb55 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/check.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/check.h diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/colorprint.cc b/src/third_party/benchmark-1.4.1/benchmark/src/colorprint.cc index 2dec4a8b28b..2dec4a8b28b 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/colorprint.cc +++ b/src/third_party/benchmark-1.4.1/benchmark/src/colorprint.cc diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/colorprint.h b/src/third_party/benchmark-1.4.1/benchmark/src/colorprint.h index 9f6fab9b342..9f6fab9b342 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/colorprint.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/colorprint.h diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/commandlineflags.cc b/src/third_party/benchmark-1.4.1/benchmark/src/commandlineflags.cc index 2fc92517a32..2fc92517a32 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/commandlineflags.cc +++ b/src/third_party/benchmark-1.4.1/benchmark/src/commandlineflags.cc diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/commandlineflags.h b/src/third_party/benchmark-1.4.1/benchmark/src/commandlineflags.h index 945c9a9fc4a..945c9a9fc4a 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/commandlineflags.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/commandlineflags.h diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/complexity.cc b/src/third_party/benchmark-1.4.1/benchmark/src/complexity.cc index 88832698ef6..97bf6e09b30 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/complexity.cc +++ b/src/third_party/benchmark-1.4.1/benchmark/src/complexity.cc @@ -28,18 +28,18 @@ namespace benchmark { BigOFunc* FittingCurve(BigO complexity) { switch (complexity) { case oN: - return [](int n) -> double { return n; }; + return [](int64_t n) -> double { return static_cast<double>(n); }; case oNSquared: - return [](int n) -> double { return std::pow(n, 2); }; + return [](int64_t n) -> double { return std::pow(n, 2); }; case oNCubed: - return [](int n) -> double { return std::pow(n, 3); }; + return [](int64_t n) -> double { return std::pow(n, 3); }; case oLogN: - return [](int n) { return log2(n); }; + return [](int64_t n) { return log2(n); }; case oNLogN: - return [](int n) { return n * log2(n); }; + return [](int64_t n) { return n * log2(n); }; case o1: default: - return [](int) { return 1.0; }; + return [](int64_t) { return 1.0; }; } } @@ -65,15 +65,15 @@ std::string GetBigOString(BigO complexity) { // Find the coefficient for the high-order term in the running time, by // minimizing the sum of squares of relative error, for the fitting curve -// given by the lambda expresion. +// given by the lambda expression. // - n : Vector containing the size of the benchmark tests. // - time : Vector containing the times for the benchmark tests. -// - fitting_curve : lambda expresion (e.g. [](int n) {return n; };). +// - fitting_curve : lambda expression (e.g. [](int64_t n) {return n; };). // For a deeper explanation on the algorithm logic, look the README file at // http://github.com/ismaelJimenez/Minimal-Cpp-Least-Squared-Fit -LeastSq MinimalLeastSq(const std::vector<int>& n, +LeastSq MinimalLeastSq(const std::vector<int64_t>& n, const std::vector<double>& time, BigOFunc* fitting_curve) { double sigma_gn = 0.0; @@ -117,7 +117,7 @@ LeastSq MinimalLeastSq(const std::vector<int>& n, // - complexity : If different than oAuto, the fitting curve will stick to // this one. If it is oAuto, it will be calculated the best // fitting curve. -LeastSq MinimalLeastSq(const std::vector<int>& n, +LeastSq MinimalLeastSq(const std::vector<int64_t>& n, const std::vector<double>& time, const BigO complexity) { CHECK_EQ(n.size(), time.size()); CHECK_GE(n.size(), 2); // Do not compute fitting curve is less than two @@ -157,7 +157,7 @@ std::vector<BenchmarkReporter::Run> ComputeBigO( if (reports.size() < 2) return results; // Accumulators. - std::vector<int> n; + std::vector<int64_t> n; std::vector<double> real_time; std::vector<double> cpu_time; diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/complexity.h b/src/third_party/benchmark-1.4.1/benchmark/src/complexity.h index df29b48d29b..df29b48d29b 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/complexity.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/complexity.h diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/console_reporter.cc b/src/third_party/benchmark-1.4.1/benchmark/src/console_reporter.cc index 1226d23444f..48920ca7829 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/console_reporter.cc +++ b/src/third_party/benchmark-1.4.1/benchmark/src/console_reporter.cc @@ -148,12 +148,14 @@ void ConsoleReporter::PrintRunData(const Run& result) { } for (auto& c : result.counters) { + const std::size_t cNameLen = std::max(std::string::size_type(10), + c.first.length()); auto const& s = HumanReadableNumber(c.second.value, 1000); if (output_options_ & OO_Tabular) { if (c.second.flags & Counter::kIsRate) { - printer(Out, COLOR_DEFAULT, " %8s/s", s.c_str()); + printer(Out, COLOR_DEFAULT, " %*s/s", cNameLen - 2, s.c_str()); } else { - printer(Out, COLOR_DEFAULT, " %10s", s.c_str()); + printer(Out, COLOR_DEFAULT, " %*s", cNameLen, s.c_str()); } } else { const char* unit = (c.second.flags & Counter::kIsRate) ? "/s" : ""; diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/counter.cc b/src/third_party/benchmark-1.4.1/benchmark/src/counter.cc index ed1aa044ee7..ed1aa044ee7 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/counter.cc +++ b/src/third_party/benchmark-1.4.1/benchmark/src/counter.cc diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/counter.h b/src/third_party/benchmark-1.4.1/benchmark/src/counter.h index dd6865a31d7..dd6865a31d7 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/counter.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/counter.h diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/csv_reporter.cc b/src/third_party/benchmark-1.4.1/benchmark/src/csv_reporter.cc index 35510645b08..35510645b08 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/csv_reporter.cc +++ b/src/third_party/benchmark-1.4.1/benchmark/src/csv_reporter.cc diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/cycleclock.h b/src/third_party/benchmark-1.4.1/benchmark/src/cycleclock.h index e8a5ae48862..3b376ac57d5 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/cycleclock.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/cycleclock.h @@ -159,10 +159,10 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { struct timeval tv; gettimeofday(&tv, nullptr); return static_cast<int64_t>(tv.tv_sec) * 1000000 + tv.tv_usec; -#elif defined(__s390__) - // MONGODB MODIFICATION: Return the CPU clock on s390x. +#elif defined(__s390__) // Covers both s390 and s390x. + // Return the CPU clock. uint64_t tsc; - asm("\tstck\t%0\n" : "=Q" (tsc) : : "cc"); + asm("stck %0" : "=Q" (tsc) : : "cc"); return tsc; #else // The soft failover to a generic implementation is automatic only for ARM. diff --git a/src/third_party/benchmark-1.4.1/benchmark/src/internal_macros.h b/src/third_party/benchmark-1.4.1/benchmark/src/internal_macros.h new file mode 100644 index 00000000000..edb8a5c0a35 --- /dev/null +++ b/src/third_party/benchmark-1.4.1/benchmark/src/internal_macros.h @@ -0,0 +1,89 @@ +#ifndef BENCHMARK_INTERNAL_MACROS_H_ +#define BENCHMARK_INTERNAL_MACROS_H_ + +#include "benchmark/benchmark.h" + +#ifndef __has_feature +#define __has_feature(x) 0 +#endif +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#if defined(__clang__) + #if !defined(COMPILER_CLANG) + #define COMPILER_CLANG + #endif +#elif defined(_MSC_VER) + #if !defined(COMPILER_MSVC) + #define COMPILER_MSVC + #endif +#elif defined(__GNUC__) + #if !defined(COMPILER_GCC) + #define COMPILER_GCC + #endif +#endif + +#if __has_feature(cxx_attributes) + #define BENCHMARK_NORETURN [[noreturn]] +#elif defined(__GNUC__) + #define BENCHMARK_NORETURN __attribute__((noreturn)) +#elif defined(COMPILER_MSVC) + #define BENCHMARK_NORETURN __declspec(noreturn) +#else + #define BENCHMARK_NORETURN +#endif + +#if defined(__CYGWIN__) + #define BENCHMARK_OS_CYGWIN 1 +#elif defined(_WIN32) + #define BENCHMARK_OS_WINDOWS 1 +#elif defined(__APPLE__) + #define BENCHMARK_OS_APPLE 1 + #include "TargetConditionals.h" + #if defined(TARGET_OS_MAC) + #define BENCHMARK_OS_MACOSX 1 + #if defined(TARGET_OS_IPHONE) + #define BENCHMARK_OS_IOS 1 + #endif + #endif +#elif defined(__FreeBSD__) + #define BENCHMARK_OS_FREEBSD 1 +#elif defined(__NetBSD__) + #define BENCHMARK_OS_NETBSD 1 +#elif defined(__OpenBSD__) + #define BENCHMARK_OS_OPENBSD 1 +#elif defined(__linux__) + #define BENCHMARK_OS_LINUX 1 +#elif defined(__native_client__) + #define BENCHMARK_OS_NACL 1 +#elif defined(__EMSCRIPTEN__) + #define BENCHMARK_OS_EMSCRIPTEN 1 +#elif defined(__rtems__) + #define BENCHMARK_OS_RTEMS 1 +#elif defined(__Fuchsia__) +#define BENCHMARK_OS_FUCHSIA 1 +#elif defined (__SVR4) && defined (__sun) +#define BENCHMARK_OS_SOLARIS 1 +#endif + +#if !__has_feature(cxx_exceptions) && !defined(__cpp_exceptions) \ + && !defined(__EXCEPTIONS) + #define BENCHMARK_HAS_NO_EXCEPTIONS +#endif + +#if defined(COMPILER_CLANG) || defined(COMPILER_GCC) + #define BENCHMARK_MAYBE_UNUSED __attribute__((unused)) +#else + #define BENCHMARK_MAYBE_UNUSED +#endif + +#if defined(COMPILER_GCC) || __has_builtin(__builtin_unreachable) + #define BENCHMARK_UNREACHABLE() __builtin_unreachable() +#elif defined(COMPILER_MSVC) + #define BENCHMARK_UNREACHABLE() __assume(false) +#else + #define BENCHMARK_UNREACHABLE() ((void)0) +#endif + +#endif // BENCHMARK_INTERNAL_MACROS_H_ diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/json_reporter.cc b/src/third_party/benchmark-1.4.1/benchmark/src/json_reporter.cc index a49f5b0fb5d..685d6b097dc 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/json_reporter.cc +++ b/src/third_party/benchmark-1.4.1/benchmark/src/json_reporter.cc @@ -32,15 +32,15 @@ namespace benchmark { namespace { std::string FormatKV(std::string const& key, std::string const& value) { - return StringPrintF("\"%s\": \"%s\"", key.c_str(), value.c_str()); + return StrFormat("\"%s\": \"%s\"", key.c_str(), value.c_str()); } std::string FormatKV(std::string const& key, const char* value) { - return StringPrintF("\"%s\": \"%s\"", key.c_str(), value); + return StrFormat("\"%s\": \"%s\"", key.c_str(), value); } std::string FormatKV(std::string const& key, bool value) { - return StringPrintF("\"%s\": %s", key.c_str(), value ? "true" : "false"); + return StrFormat("\"%s\": %s", key.c_str(), value ? "true" : "false"); } std::string FormatKV(std::string const& key, int64_t value) { @@ -77,13 +77,41 @@ bool JSONReporter::ReportContext(const Context& context) { std::string walltime_value = LocalDateTimeString(); out << indent << FormatKV("date", walltime_value) << ",\n"; - out << indent << FormatKV("num_cpus", static_cast<int64_t>(context.num_cpus)) + if (Context::executable_name) { + out << indent << FormatKV("executable", Context::executable_name) << ",\n"; + } + + CPUInfo const& info = context.cpu_info; + out << indent << FormatKV("num_cpus", static_cast<int64_t>(info.num_cpus)) << ",\n"; - out << indent << FormatKV("mhz_per_cpu", RoundDouble(context.mhz_per_cpu)) + out << indent + << FormatKV("mhz_per_cpu", + RoundDouble(info.cycles_per_second / 1000000.0)) << ",\n"; - out << indent << FormatKV("cpu_scaling_enabled", context.cpu_scaling_enabled) + out << indent << FormatKV("cpu_scaling_enabled", info.scaling_enabled) << ",\n"; + out << indent << "\"caches\": [\n"; + indent = std::string(6, ' '); + std::string cache_indent(8, ' '); + for (size_t i = 0; i < info.caches.size(); ++i) { + auto& CI = info.caches[i]; + out << indent << "{\n"; + out << cache_indent << FormatKV("type", CI.type) << ",\n"; + out << cache_indent << FormatKV("level", static_cast<int64_t>(CI.level)) + << ",\n"; + out << cache_indent + << FormatKV("size", static_cast<int64_t>(CI.size) * 1000u) << ",\n"; + out << cache_indent + << FormatKV("num_sharing", static_cast<int64_t>(CI.num_sharing)) + << "\n"; + out << indent << "}"; + if (i != info.caches.size() - 1) out << ","; + out << "\n"; + } + indent = std::string(4, ' '); + out << indent << "],\n"; + #if defined(NDEBUG) const char build_type[] = "release"; #else diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/log.h b/src/third_party/benchmark-1.4.1/benchmark/src/log.h index d06e1031db1..d06e1031db1 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/log.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/log.h diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/mutex.h b/src/third_party/benchmark-1.4.1/benchmark/src/mutex.h index 5f461d05a0c..5f461d05a0c 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/mutex.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/mutex.h diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/re.h b/src/third_party/benchmark-1.4.1/benchmark/src/re.h index 01e9736505e..924d2f0ba7e 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/re.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/re.h @@ -17,19 +17,31 @@ #include "internal_macros.h" +#if !defined(HAVE_STD_REGEX) && \ + !defined(HAVE_GNU_POSIX_REGEX) && \ + !defined(HAVE_POSIX_REGEX) + // No explicit regex selection; detect based on builtin hints. + #if defined(BENCHMARK_OS_LINUX) || defined(BENCHMARK_OS_APPLE) + #define HAVE_POSIX_REGEX 1 + #elif __cplusplus >= 199711L + #define HAVE_STD_REGEX 1 + #endif +#endif + // Prefer C regex libraries when compiling w/o exceptions so that we can // correctly report errors. -#if defined(BENCHMARK_HAS_NO_EXCEPTIONS) && defined(HAVE_STD_REGEX) && \ +#if defined(BENCHMARK_HAS_NO_EXCEPTIONS) && \ + defined(BENCHMARK_HAVE_STD_REGEX) && \ (defined(HAVE_GNU_POSIX_REGEX) || defined(HAVE_POSIX_REGEX)) -#undef HAVE_STD_REGEX + #undef HAVE_STD_REGEX #endif #if defined(HAVE_STD_REGEX) -#include <regex> + #include <regex> #elif defined(HAVE_GNU_POSIX_REGEX) -#include <gnuregex.h> + #include <gnuregex.h> #elif defined(HAVE_POSIX_REGEX) -#include <regex.h> + #include <regex.h> #else #error No regular expression backend was found! #endif @@ -64,7 +76,7 @@ class Regex { #elif defined(HAVE_POSIX_REGEX) || defined(HAVE_GNU_POSIX_REGEX) regex_t re_; #else -#error No regular expression backend implementation available + #error No regular expression backend implementation available #endif }; diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/reporter.cc b/src/third_party/benchmark-1.4.1/benchmark/src/reporter.cc index 9a0830b03bd..4b40aaec8b9 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/reporter.cc +++ b/src/third_party/benchmark-1.4.1/benchmark/src/reporter.cc @@ -35,12 +35,27 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out, CHECK(out) << "cannot be null"; auto &Out = *out; - Out << "Run on (" << context.num_cpus << " X " << context.mhz_per_cpu - << " MHz CPU " << ((context.num_cpus > 1) ? "s" : "") << ")\n"; - Out << LocalDateTimeString() << "\n"; - if (context.cpu_scaling_enabled) { + if (context.executable_name) + Out << "Running " << context.executable_name << "\n"; + + const CPUInfo &info = context.cpu_info; + Out << "Run on (" << info.num_cpus << " X " + << (info.cycles_per_second / 1000000.0) << " MHz CPU " + << ((info.num_cpus > 1) ? "s" : "") << ")\n"; + if (info.caches.size() != 0) { + Out << "CPU Caches:\n"; + for (auto &CInfo : info.caches) { + Out << " L" << CInfo.level << " " << CInfo.type << " " + << (CInfo.size / 1000) << "K"; + if (CInfo.num_sharing != 0) + Out << " (x" << (info.num_cpus / CInfo.num_sharing) << ")"; + Out << "\n"; + } + } + + if (info.scaling_enabled) { Out << "***WARNING*** CPU scaling is enabled, the benchmark " "real time measurements may be noisy and will incur extra " "overhead.\n"; @@ -52,6 +67,11 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out, #endif } +// No initializer because it's already initialized to NULL. +const char* BenchmarkReporter::Context::executable_name; + +BenchmarkReporter::Context::Context() : cpu_info(CPUInfo::Get()) {} + double BenchmarkReporter::Run::GetAdjustedRealTime() const { double new_time = real_accumulated_time * GetTimeUnitMultiplier(time_unit); if (iterations != 0) new_time /= static_cast<double>(iterations); diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/sleep.cc b/src/third_party/benchmark-1.4.1/benchmark/src/sleep.cc index 54aa04a4224..54aa04a4224 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/sleep.cc +++ b/src/third_party/benchmark-1.4.1/benchmark/src/sleep.cc diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/sleep.h b/src/third_party/benchmark-1.4.1/benchmark/src/sleep.h index f98551afe28..f98551afe28 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/sleep.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/sleep.h diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/statistics.cc b/src/third_party/benchmark-1.4.1/benchmark/src/statistics.cc index 5932ad43860..1c91e1015ab 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/statistics.cc +++ b/src/third_party/benchmark-1.4.1/benchmark/src/statistics.cc @@ -30,22 +30,25 @@ auto StatisticsSum = [](const std::vector<double>& v) { }; double StatisticsMean(const std::vector<double>& v) { - if (v.size() == 0) return 0.0; + if (v.empty()) return 0.0; return StatisticsSum(v) * (1.0 / v.size()); } double StatisticsMedian(const std::vector<double>& v) { if (v.size() < 3) return StatisticsMean(v); - std::vector<double> partial; - // we need roundDown(count/2)+1 slots - partial.resize(1 + (v.size() / 2)); - std::partial_sort_copy(v.begin(), v.end(), partial.begin(), partial.end()); - // did we have odd number of samples? - // if yes, then the last element of partially-sorted vector is the median - // it no, then the average of the last two elements is the median + std::vector<double> copy(v); + + auto center = copy.begin() + v.size() / 2; + std::nth_element(copy.begin(), center, copy.end()); + + // did we have an odd number of samples? + // if yes, then center is the median + // it no, then we are looking for the average between center and the value before if(v.size() % 2 == 1) - return partial.back(); - return (partial[partial.size() - 2] + partial[partial.size() - 1]) / 2.0; + return *center; + auto center2 = copy.begin() + v.size() / 2 - 1; + std::nth_element(copy.begin(), center2, copy.end()); + return (*center + *center2) / 2.0; } // Return the sum of the squares of this sample set @@ -62,7 +65,7 @@ auto Sqrt = [](const double dat) { double StatisticsStdDev(const std::vector<double>& v) { const auto mean = StatisticsMean(v); - if (v.size() == 0) return mean; + if (v.empty()) return mean; // Sample standard deviation is undefined for n = 1 if (v.size() == 1) diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/statistics.h b/src/third_party/benchmark-1.4.1/benchmark/src/statistics.h index 7eccc85536a..7eccc85536a 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/statistics.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/statistics.h diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/string_util.cc b/src/third_party/benchmark-1.4.1/benchmark/src/string_util.cc index 29edb2a4683..ebc3acebd2a 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/string_util.cc +++ b/src/third_party/benchmark-1.4.1/benchmark/src/string_util.cc @@ -122,7 +122,7 @@ std::string HumanReadableNumber(double n, double one_k) { return ToBinaryStringFullySpecified(n, 1.1, 1, one_k); } -std::string StringPrintFImp(const char* msg, va_list args) { +std::string StrFormatImp(const char* msg, va_list args) { // we might need a second shot at this, so pre-emptivly make a copy va_list args_cp; va_copy(args_cp, args); @@ -152,10 +152,10 @@ std::string StringPrintFImp(const char* msg, va_list args) { return std::string(buff_ptr.get()); } -std::string StringPrintF(const char* format, ...) { +std::string StrFormat(const char* format, ...) { va_list args; va_start(args, format); - std::string tmp = StringPrintFImp(format, args); + std::string tmp = StrFormatImp(format, args); va_end(args); return tmp; } diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/string_util.h b/src/third_party/benchmark-1.4.1/benchmark/src/string_util.h index c3d53bfd334..e70e7698724 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/string_util.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/string_util.h @@ -12,23 +12,23 @@ void AppendHumanReadable(int n, std::string* str); std::string HumanReadableNumber(double n, double one_k = 1024.0); -std::string StringPrintF(const char* format, ...); +std::string StrFormat(const char* format, ...); -inline std::ostream& StringCatImp(std::ostream& out) BENCHMARK_NOEXCEPT { +inline std::ostream& StrCatImp(std::ostream& out) BENCHMARK_NOEXCEPT { return out; } template <class First, class... Rest> -inline std::ostream& StringCatImp(std::ostream& out, First&& f, +inline std::ostream& StrCatImp(std::ostream& out, First&& f, Rest&&... rest) { out << std::forward<First>(f); - return StringCatImp(out, std::forward<Rest>(rest)...); + return StrCatImp(out, std::forward<Rest>(rest)...); } template <class... Args> inline std::string StrCat(Args&&... args) { std::ostringstream ss; - StringCatImp(ss, std::forward<Args>(args)...); + StrCatImp(ss, std::forward<Args>(args)...); return ss.str(); } diff --git a/src/third_party/benchmark-1.4.1/benchmark/src/sysinfo.cc b/src/third_party/benchmark-1.4.1/benchmark/src/sysinfo.cc new file mode 100644 index 00000000000..d19d0ef4c1e --- /dev/null +++ b/src/third_party/benchmark-1.4.1/benchmark/src/sysinfo.cc @@ -0,0 +1,587 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "internal_macros.h" + +#ifdef BENCHMARK_OS_WINDOWS +#include <Shlwapi.h> +#undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA +#include <VersionHelpers.h> +#include <Windows.h> +#else +#include <fcntl.h> +#ifndef BENCHMARK_OS_FUCHSIA +#include <sys/resource.h> +#endif +#include <sys/time.h> +#include <sys/types.h> // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD +#include <unistd.h> +#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX || \ + defined BENCHMARK_OS_NETBSD || defined BENCHMARK_OS_OPENBSD +#define BENCHMARK_HAS_SYSCTL +#include <sys/sysctl.h> +#endif +#endif +#if defined(BENCHMARK_OS_SOLARIS) +#include <kstat.h> +#endif + +#include <algorithm> +#include <array> +#include <bitset> +#include <cerrno> +#include <climits> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <fstream> +#include <iostream> +#include <iterator> +#include <limits> +#include <memory> +#include <sstream> + +#include "check.h" +#include "cycleclock.h" +#include "internal_macros.h" +#include "log.h" +#include "sleep.h" +#include "string_util.h" + +namespace benchmark { +namespace { + +void PrintImp(std::ostream& out) { out << std::endl; } + +template <class First, class... Rest> +void PrintImp(std::ostream& out, First&& f, Rest&&... rest) { + out << std::forward<First>(f); + PrintImp(out, std::forward<Rest>(rest)...); +} + +template <class... Args> +BENCHMARK_NORETURN void PrintErrorAndDie(Args&&... args) { + PrintImp(std::cerr, std::forward<Args>(args)...); + std::exit(EXIT_FAILURE); +} + +#ifdef BENCHMARK_HAS_SYSCTL + +/// ValueUnion - A type used to correctly alias the byte-for-byte output of +/// `sysctl` with the result type it's to be interpreted as. +struct ValueUnion { + union DataT { + uint32_t uint32_value; + uint64_t uint64_value; + // For correct aliasing of union members from bytes. + char bytes[8]; + }; + using DataPtr = std::unique_ptr<DataT, decltype(&std::free)>; + + // The size of the data union member + its trailing array size. + size_t Size; + DataPtr Buff; + + public: + ValueUnion() : Size(0), Buff(nullptr, &std::free) {} + + explicit ValueUnion(size_t BuffSize) + : Size(sizeof(DataT) + BuffSize), + Buff(::new (std::malloc(Size)) DataT(), &std::free) {} + + ValueUnion(ValueUnion&& other) = default; + + explicit operator bool() const { return bool(Buff); } + + char* data() const { return Buff->bytes; } + + std::string GetAsString() const { return std::string(data()); } + + int64_t GetAsInteger() const { + if (Size == sizeof(Buff->uint32_value)) + return static_cast<int32_t>(Buff->uint32_value); + else if (Size == sizeof(Buff->uint64_value)) + return static_cast<int64_t>(Buff->uint64_value); + BENCHMARK_UNREACHABLE(); + } + + uint64_t GetAsUnsigned() const { + if (Size == sizeof(Buff->uint32_value)) + return Buff->uint32_value; + else if (Size == sizeof(Buff->uint64_value)) + return Buff->uint64_value; + BENCHMARK_UNREACHABLE(); + } + + template <class T, int N> + std::array<T, N> GetAsArray() { + const int ArrSize = sizeof(T) * N; + CHECK_LE(ArrSize, Size); + std::array<T, N> Arr; + std::memcpy(Arr.data(), data(), ArrSize); + return Arr; + } +}; + +ValueUnion GetSysctlImp(std::string const& Name) { +#if defined BENCHMARK_OS_OPENBSD + int mib[2]; + + mib[0] = CTL_HW; + if ((Name == "hw.ncpu") || (Name == "hw.cpuspeed")){ + ValueUnion buff(sizeof(int)); + + if (Name == "hw.ncpu") { + mib[1] = HW_NCPU; + } else { + mib[1] = HW_CPUSPEED; + } + + if (sysctl(mib, 2, buff.data(), &buff.Size, nullptr, 0) == -1) { + return ValueUnion(); + } + return buff; + } + return ValueUnion(); +#else + size_t CurBuffSize = 0; + if (sysctlbyname(Name.c_str(), nullptr, &CurBuffSize, nullptr, 0) == -1) + return ValueUnion(); + + ValueUnion buff(CurBuffSize); + if (sysctlbyname(Name.c_str(), buff.data(), &buff.Size, nullptr, 0) == 0) + return buff; + return ValueUnion(); +#endif +} + +BENCHMARK_MAYBE_UNUSED +bool GetSysctl(std::string const& Name, std::string* Out) { + Out->clear(); + auto Buff = GetSysctlImp(Name); + if (!Buff) return false; + Out->assign(Buff.data()); + return true; +} + +template <class Tp, + class = typename std::enable_if<std::is_integral<Tp>::value>::type> +bool GetSysctl(std::string const& Name, Tp* Out) { + *Out = 0; + auto Buff = GetSysctlImp(Name); + if (!Buff) return false; + *Out = static_cast<Tp>(Buff.GetAsUnsigned()); + return true; +} + +template <class Tp, size_t N> +bool GetSysctl(std::string const& Name, std::array<Tp, N>* Out) { + auto Buff = GetSysctlImp(Name); + if (!Buff) return false; + *Out = Buff.GetAsArray<Tp, N>(); + return true; +} +#endif + +template <class ArgT> +bool ReadFromFile(std::string const& fname, ArgT* arg) { + *arg = ArgT(); + std::ifstream f(fname.c_str()); + if (!f.is_open()) return false; + f >> *arg; + return f.good(); +} + +bool CpuScalingEnabled(int num_cpus) { + // We don't have a valid CPU count, so don't even bother. + if (num_cpus <= 0) return false; +#ifndef BENCHMARK_OS_WINDOWS + // 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. + std::string res; + for (int cpu = 0; cpu < num_cpus; ++cpu) { + std::string governor_file = + StrCat("/sys/devices/system/cpu/cpu", cpu, "/cpufreq/scaling_governor"); + if (ReadFromFile(governor_file, &res) && res != "performance") return true; + } +#endif + return false; +} + +int CountSetBitsInCPUMap(std::string Val) { + auto CountBits = [](std::string Part) { + using CPUMask = std::bitset<sizeof(std::uintptr_t) * CHAR_BIT>; + Part = "0x" + Part; + CPUMask Mask(std::stoul(Part, nullptr, 16)); + return static_cast<int>(Mask.count()); + }; + size_t Pos; + int total = 0; + while ((Pos = Val.find(',')) != std::string::npos) { + total += CountBits(Val.substr(0, Pos)); + Val = Val.substr(Pos + 1); + } + if (!Val.empty()) { + total += CountBits(Val); + } + return total; +} + +BENCHMARK_MAYBE_UNUSED +std::vector<CPUInfo::CacheInfo> GetCacheSizesFromKVFS() { + std::vector<CPUInfo::CacheInfo> res; + std::string dir = "/sys/devices/system/cpu/cpu0/cache/"; + int Idx = 0; + while (true) { + CPUInfo::CacheInfo info; + std::string FPath = StrCat(dir, "index", Idx++, "/"); + std::ifstream f(StrCat(FPath, "size").c_str()); + if (!f.is_open()) break; + std::string suffix; + f >> info.size; + if (f.fail()) + PrintErrorAndDie("Failed while reading file '", FPath, "size'"); + if (f.good()) { + f >> suffix; + if (f.bad()) + PrintErrorAndDie( + "Invalid cache size format: failed to read size suffix"); + else if (f && suffix != "K") + PrintErrorAndDie("Invalid cache size format: Expected bytes ", suffix); + else if (suffix == "K") + info.size *= 1000; + } + if (!ReadFromFile(StrCat(FPath, "type"), &info.type)) + PrintErrorAndDie("Failed to read from file ", FPath, "type"); + if (!ReadFromFile(StrCat(FPath, "level"), &info.level)) + PrintErrorAndDie("Failed to read from file ", FPath, "level"); + std::string map_str; + if (!ReadFromFile(StrCat(FPath, "shared_cpu_map"), &map_str)) + PrintErrorAndDie("Failed to read from file ", FPath, "shared_cpu_map"); + info.num_sharing = CountSetBitsInCPUMap(map_str); + res.push_back(info); + } + + return res; +} + +#ifdef BENCHMARK_OS_MACOSX +std::vector<CPUInfo::CacheInfo> GetCacheSizesMacOSX() { + std::vector<CPUInfo::CacheInfo> res; + std::array<uint64_t, 4> CacheCounts{{0, 0, 0, 0}}; + GetSysctl("hw.cacheconfig", &CacheCounts); + + struct { + std::string name; + std::string type; + int level; + size_t num_sharing; + } Cases[] = {{"hw.l1dcachesize", "Data", 1, CacheCounts[1]}, + {"hw.l1icachesize", "Instruction", 1, CacheCounts[1]}, + {"hw.l2cachesize", "Unified", 2, CacheCounts[2]}, + {"hw.l3cachesize", "Unified", 3, CacheCounts[3]}}; + for (auto& C : Cases) { + int val; + if (!GetSysctl(C.name, &val)) continue; + CPUInfo::CacheInfo info; + info.type = C.type; + info.level = C.level; + info.size = val; + info.num_sharing = static_cast<int>(C.num_sharing); + res.push_back(std::move(info)); + } + return res; +} +#elif defined(BENCHMARK_OS_WINDOWS) +std::vector<CPUInfo::CacheInfo> GetCacheSizesWindows() { + std::vector<CPUInfo::CacheInfo> res; + DWORD buffer_size = 0; + using PInfo = SYSTEM_LOGICAL_PROCESSOR_INFORMATION; + using CInfo = CACHE_DESCRIPTOR; + + using UPtr = std::unique_ptr<PInfo, decltype(&std::free)>; + GetLogicalProcessorInformation(nullptr, &buffer_size); + UPtr buff((PInfo*)malloc(buffer_size), &std::free); + if (!GetLogicalProcessorInformation(buff.get(), &buffer_size)) + PrintErrorAndDie("Failed during call to GetLogicalProcessorInformation: ", + GetLastError()); + + PInfo* it = buff.get(); + PInfo* end = buff.get() + (buffer_size / sizeof(PInfo)); + + for (; it != end; ++it) { + if (it->Relationship != RelationCache) continue; + using BitSet = std::bitset<sizeof(ULONG_PTR) * CHAR_BIT>; + BitSet B(it->ProcessorMask); + // To prevent duplicates, only consider caches where CPU 0 is specified + if (!B.test(0)) continue; + CInfo* Cache = &it->Cache; + CPUInfo::CacheInfo C; + C.num_sharing = static_cast<int>(B.count()); + C.level = Cache->Level; + C.size = Cache->Size; + switch (Cache->Type) { + case CacheUnified: + C.type = "Unified"; + break; + case CacheInstruction: + C.type = "Instruction"; + break; + case CacheData: + C.type = "Data"; + break; + case CacheTrace: + C.type = "Trace"; + break; + default: + C.type = "Unknown"; + break; + } + res.push_back(C); + } + return res; +} +#endif + +std::vector<CPUInfo::CacheInfo> GetCacheSizes() { +#ifdef BENCHMARK_OS_MACOSX + return GetCacheSizesMacOSX(); +#elif defined(BENCHMARK_OS_WINDOWS) + return GetCacheSizesWindows(); +#else + return GetCacheSizesFromKVFS(); +#endif +} + +int GetNumCPUs() { +#ifdef BENCHMARK_HAS_SYSCTL + int NumCPU = -1; + if (GetSysctl("hw.ncpu", &NumCPU)) return NumCPU; + fprintf(stderr, "Err: %s\n", strerror(errno)); + std::exit(EXIT_FAILURE); +#elif defined(BENCHMARK_OS_WINDOWS) + SYSTEM_INFO sysinfo; + // Use memset as opposed to = {} to avoid GCC missing initializer false + // positives. + std::memset(&sysinfo, 0, sizeof(SYSTEM_INFO)); + GetSystemInfo(&sysinfo); + return sysinfo.dwNumberOfProcessors; // number of logical + // processors in the current + // group +#elif defined(BENCHMARK_OS_SOLARIS) + // Returns -1 in case of a failure. + int NumCPU = sysconf(_SC_NPROCESSORS_ONLN); + if (NumCPU < 0) { + fprintf(stderr, + "sysconf(_SC_NPROCESSORS_ONLN) failed with error: %s\n", + strerror(errno)); + } + return NumCPU; +#else + int NumCPUs = 0; + int MaxID = -1; + std::ifstream f("/proc/cpuinfo"); + if (!f.is_open()) { + std::cerr << "failed to open /proc/cpuinfo\n"; + return -1; + } + const std::string Key = "processor"; + std::string ln; + while (std::getline(f, ln)) { + if (ln.empty()) continue; + size_t SplitIdx = ln.find(':'); + std::string value; + if (SplitIdx != std::string::npos) value = ln.substr(SplitIdx + 1); + if (ln.size() >= Key.size() && ln.compare(0, Key.size(), Key) == 0) { + NumCPUs++; + if (!value.empty()) { + int CurID = std::stoi(value); + MaxID = std::max(CurID, MaxID); + } + } + } + if (f.bad()) { + std::cerr << "Failure reading /proc/cpuinfo\n"; + return -1; + } + if (!f.eof()) { + std::cerr << "Failed to read to end of /proc/cpuinfo\n"; + return -1; + } + f.close(); + + if ((MaxID + 1) != NumCPUs) { + fprintf(stderr, + "CPU ID assignments in /proc/cpuinfo seem messed up." + " This is usually caused by a bad BIOS.\n"); + } + return NumCPUs; +#endif + BENCHMARK_UNREACHABLE(); +} + +double GetCPUCyclesPerSecond() { +#if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN + long freq; + + // If the kernel is exporting the tsc frequency use that. There are issues + // where cpuinfo_max_freq cannot be relied on because the BIOS may be + // exporintg an invalid p-state (on x86) or p-states may be used to put the + // processor in a new mode (turbo mode). Essentially, those frequencies + // cannot always be relied upon. The same reasons apply to /proc/cpuinfo as + // well. + if (ReadFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq) + // If CPU scaling is in effect, we want to use the *maximum* frequency, + // not whatever CPU speed some random processor happens to be using now. + || ReadFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", + &freq)) { + // The value is in kHz (as the file name suggests). For example, on a + // 2GHz warpstation, the file contains the value "2000000". + return freq * 1000.0; + } + + const double error_value = -1; + double bogo_clock = error_value; + + std::ifstream f("/proc/cpuinfo"); + if (!f.is_open()) { + std::cerr << "failed to open /proc/cpuinfo\n"; + return error_value; + } + + auto startsWithKey = [](std::string const& Value, std::string const& Key) { + if (Key.size() > Value.size()) return false; + auto Cmp = [&](char X, char Y) { + return std::tolower(X) == std::tolower(Y); + }; + return std::equal(Key.begin(), Key.end(), Value.begin(), Cmp); + }; + + std::string ln; + while (std::getline(f, ln)) { + if (ln.empty()) continue; + size_t SplitIdx = ln.find(':'); + std::string value; + if (SplitIdx != std::string::npos) value = ln.substr(SplitIdx + 1); + // When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only + // accept positive values. Some environments (virtual machines) report zero, + // which would cause infinite looping in WallTime_Init. + if (startsWithKey(ln, "cpu MHz")) { + if (!value.empty()) { + double cycles_per_second = std::stod(value) * 1000000.0; + if (cycles_per_second > 0) return cycles_per_second; + } + } else if (startsWithKey(ln, "bogomips")) { + if (!value.empty()) { + bogo_clock = std::stod(value) * 1000000.0; + if (bogo_clock < 0.0) bogo_clock = error_value; + } + } + } + if (f.bad()) { + std::cerr << "Failure reading /proc/cpuinfo\n"; + return error_value; + } + if (!f.eof()) { + std::cerr << "Failed to read to end of /proc/cpuinfo\n"; + return error_value; + } + f.close(); + // If we found the bogomips clock, but nothing better, we'll use it (but + // we're not happy about it); otherwise, fallback to the rough estimation + // below. + if (bogo_clock >= 0.0) return bogo_clock; + +#elif defined BENCHMARK_HAS_SYSCTL + constexpr auto* FreqStr = +#if defined(BENCHMARK_OS_FREEBSD) || defined(BENCHMARK_OS_NETBSD) + "machdep.tsc_freq"; +#elif defined BENCHMARK_OS_OPENBSD + "hw.cpuspeed"; +#else + "hw.cpufrequency"; +#endif + unsigned long long hz = 0; +#if defined BENCHMARK_OS_OPENBSD + if (GetSysctl(FreqStr, &hz)) return hz * 1000000; +#else + if (GetSysctl(FreqStr, &hz)) return hz; +#endif + fprintf(stderr, "Unable to determine clock rate from sysctl: %s: %s\n", + FreqStr, strerror(errno)); + +#elif defined BENCHMARK_OS_WINDOWS + // In NT, read MHz from the registry. If we fail to do so or we're in win9x + // then make a crude estimate. + DWORD data, data_size = sizeof(data); + if (IsWindowsXPOrGreater() && + SUCCEEDED( + SHGetValueA(HKEY_LOCAL_MACHINE, + "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", + "~MHz", nullptr, &data, &data_size))) + return static_cast<double>((int64_t)data * + (int64_t)(1000 * 1000)); // was mhz +#elif defined (BENCHMARK_OS_SOLARIS) + kstat_ctl_t *kc = kstat_open(); + if (!kc) { + std::cerr << "failed to open /dev/kstat\n"; + return -1; + } + kstat_t *ksp = kstat_lookup(kc, (char*)"cpu_info", -1, (char*)"cpu_info0"); + if (!ksp) { + std::cerr << "failed to lookup in /dev/kstat\n"; + return -1; + } + if (kstat_read(kc, ksp, NULL) < 0) { + std::cerr << "failed to read from /dev/kstat\n"; + return -1; + } + kstat_named_t *knp = + (kstat_named_t*)kstat_data_lookup(ksp, (char*)"current_clock_Hz"); + if (!knp) { + std::cerr << "failed to lookup data in /dev/kstat\n"; + return -1; + } + if (knp->data_type != KSTAT_DATA_UINT64) { + std::cerr << "current_clock_Hz is of unexpected data type: " + << knp->data_type << "\n"; + return -1; + } + double clock_hz = knp->value.ui64; + kstat_close(kc); + return clock_hz; +#endif + // If we've fallen through, attempt to roughly estimate the CPU clock rate. + const int estimate_time_ms = 1000; + const auto start_ticks = cycleclock::Now(); + SleepForMilliseconds(estimate_time_ms); + return static_cast<double>(cycleclock::Now() - start_ticks); +} + +} // end namespace + +const CPUInfo& CPUInfo::Get() { + static const CPUInfo* info = new CPUInfo(); + return *info; +} + +CPUInfo::CPUInfo() + : num_cpus(GetNumCPUs()), + cycles_per_second(GetCPUCyclesPerSecond()), + caches(GetCacheSizes()), + scaling_enabled(CpuScalingEnabled(num_cpus)) {} + +} // end namespace benchmark diff --git a/src/third_party/benchmark-1.4.1/benchmark/src/thread_manager.h b/src/third_party/benchmark-1.4.1/benchmark/src/thread_manager.h new file mode 100644 index 00000000000..82b4d72b62f --- /dev/null +++ b/src/third_party/benchmark-1.4.1/benchmark/src/thread_manager.h @@ -0,0 +1,66 @@ +#ifndef BENCHMARK_THREAD_MANAGER_H +#define BENCHMARK_THREAD_MANAGER_H + +#include <atomic> + +#include "benchmark/benchmark.h" +#include "mutex.h" + +namespace benchmark { +namespace internal { + +class ThreadManager { + public: + ThreadManager(int num_threads) + : alive_threads_(num_threads), start_stop_barrier_(num_threads) {} + + Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) { + return benchmark_mutex_; + } + + bool StartStopBarrier() EXCLUDES(end_cond_mutex_) { + return start_stop_barrier_.wait(); + } + + void NotifyThreadComplete() EXCLUDES(end_cond_mutex_) { + start_stop_barrier_.removeThread(); + if (--alive_threads_ == 0) { + MutexLock lock(end_cond_mutex_); + end_condition_.notify_all(); + } + } + + void WaitForAllThreads() EXCLUDES(end_cond_mutex_) { + MutexLock lock(end_cond_mutex_); + end_condition_.wait(lock.native_handle(), + [this]() { return alive_threads_ == 0; }); + } + + public: + struct Result { + int64_t iterations = 0; + double real_time_used = 0; + double cpu_time_used = 0; + double manual_time_used = 0; + int64_t bytes_processed = 0; + int64_t items_processed = 0; + int64_t complexity_n = 0; + std::string report_label_; + std::string error_message_; + bool has_error_ = false; + UserCounters counters; + }; + GUARDED_BY(GetBenchmarkMutex()) Result results; + + private: + mutable Mutex benchmark_mutex_; + std::atomic<int> alive_threads_; + Barrier start_stop_barrier_; + Mutex end_cond_mutex_; + Condition end_condition_; +}; + +} // namespace internal +} // namespace benchmark + +#endif // BENCHMARK_THREAD_MANAGER_H diff --git a/src/third_party/benchmark-1.4.1/benchmark/src/thread_timer.h b/src/third_party/benchmark-1.4.1/benchmark/src/thread_timer.h new file mode 100644 index 00000000000..eaf108e017d --- /dev/null +++ b/src/third_party/benchmark-1.4.1/benchmark/src/thread_timer.h @@ -0,0 +1,69 @@ +#ifndef BENCHMARK_THREAD_TIMER_H +#define BENCHMARK_THREAD_TIMER_H + +#include "check.h" +#include "timers.h" + +namespace benchmark { +namespace internal { + +class ThreadTimer { + public: + ThreadTimer() = default; + + // Called by each thread + void StartTimer() { + running_ = true; + start_real_time_ = ChronoClockNow(); + start_cpu_time_ = ThreadCPUUsage(); + } + + // Called by each thread + void StopTimer() { + CHECK(running_); + running_ = false; + real_time_used_ += ChronoClockNow() - start_real_time_; + // Floating point error can result in the subtraction producing a negative + // time. Guard against that. + cpu_time_used_ += std::max<double>(ThreadCPUUsage() - start_cpu_time_, 0); + } + + // Called by each thread + void SetIterationTime(double seconds) { manual_time_used_ += seconds; } + + bool running() const { return running_; } + + // REQUIRES: timer is not running + double real_time_used() { + CHECK(!running_); + return real_time_used_; + } + + // REQUIRES: timer is not running + double cpu_time_used() { + CHECK(!running_); + return cpu_time_used_; + } + + // REQUIRES: timer is not running + double manual_time_used() { + CHECK(!running_); + return manual_time_used_; + } + + private: + bool running_ = false; // Is the timer running + double start_real_time_ = 0; // If running_ + double start_cpu_time_ = 0; // If running_ + + // Accumulated time so far (does not contain current slice if running_) + double real_time_used_ = 0; + double cpu_time_used_ = 0; + // Manually set iteration time. User sets this with SetIterationTime(seconds). + double manual_time_used_ = 0; +}; + +} // namespace internal +} // namespace benchmark + +#endif // BENCHMARK_THREAD_TIMER_H diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/timers.cc b/src/third_party/benchmark-1.4.1/benchmark/src/timers.cc index 817272d00bc..2010e2450b4 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/timers.cc +++ b/src/third_party/benchmark-1.4.1/benchmark/src/timers.cc @@ -17,11 +17,14 @@ #ifdef BENCHMARK_OS_WINDOWS #include <Shlwapi.h> +#undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA #include <VersionHelpers.h> #include <Windows.h> #else #include <fcntl.h> +#ifndef BENCHMARK_OS_FUCHSIA #include <sys/resource.h> +#endif #include <sys/time.h> #include <sys/types.h> // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD #include <unistd.h> @@ -74,7 +77,7 @@ double MakeTime(FILETIME const& kernel_time, FILETIME const& user_time) { static_cast<double>(user.QuadPart)) * 1e-7; } -#else +#elif !defined(BENCHMARK_OS_FUCHSIA) double MakeTime(struct rusage const& ru) { return (static_cast<double>(ru.ru_utime.tv_sec) + static_cast<double>(ru.ru_utime.tv_usec) * 1e-6 + @@ -162,6 +165,10 @@ double ThreadCPUUsage() { // RTEMS doesn't support CLOCK_THREAD_CPUTIME_ID. See // https://github.com/RTEMS/rtems/blob/master/cpukit/posix/src/clockgettime.c return ProcessCPUUsage(); +#elif defined(BENCHMARK_OS_SOLARIS) + struct rusage ru; + if (getrusage(RUSAGE_LWP, &ru) == 0) return MakeTime(ru); + DiagnoseAndExit("getrusage(RUSAGE_LWP, ...) failed"); #elif defined(CLOCK_THREAD_CPUTIME_ID) struct timespec ts; if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0) return MakeTime(ts); @@ -186,7 +193,6 @@ std::string DateTimeString(bool local) { std::strftime(storage, sizeof(storage), "%x %X", ::localtime(&now)); #else std::tm timeinfo; - std::memset(&timeinfo, 0, sizeof(std::tm)); ::localtime_r(&now, &timeinfo); written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo); #endif @@ -195,7 +201,6 @@ std::string DateTimeString(bool local) { written = std::strftime(storage, sizeof(storage), "%x %X", ::gmtime(&now)); #else std::tm timeinfo; - std::memset(&timeinfo, 0, sizeof(std::tm)); ::gmtime_r(&now, &timeinfo); written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo); #endif diff --git a/src/third_party/benchmark-1.3.0/benchmark/src/timers.h b/src/third_party/benchmark-1.4.1/benchmark/src/timers.h index 65606ccd93d..65606ccd93d 100644 --- a/src/third_party/benchmark-1.3.0/benchmark/src/timers.h +++ b/src/third_party/benchmark-1.4.1/benchmark/src/timers.h diff --git a/src/third_party/benchmark-1.3.0/patches/0003-Remove-deprecated-benchmark-fixture-function-decl.patch b/src/third_party/benchmark-1.4.1/patches/0001-Remove-deprecated-benchmark-fixture-function-decl.patch index b3686af4481..21430e250ca 100644 --- a/src/third_party/benchmark-1.3.0/patches/0003-Remove-deprecated-benchmark-fixture-function-decl.patch +++ b/src/third_party/benchmark-1.4.1/patches/0001-Remove-deprecated-benchmark-fixture-function-decl.patch @@ -5,13 +5,13 @@ Subject: [PATCH] SERVER-33560 Remove deprecated Fixture function declarations from Google Benchmark --- - .../benchmark-1.3.0/benchmark/include/benchmark/benchmark.h | 10 ++++------ + .../benchmark-1.4.1/benchmark/include/benchmark/benchmark.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) -diff --git a/src/third_party/benchmark-1.3.0/benchmark/include/benchmark/benchmark.h b/src/third_party/benchmark-1.3.0/benchmark/include/benchmark/benchmark.h +diff --git a/src/third_party/benchmark-1.4.1/benchmark/include/benchmark/benchmark.h b/src/third_party/benchmark-1.4.1/benchmark/include/benchmark/benchmark.h index 15ed02e538..2183c8a1d2 100644 ---- a/src/third_party/benchmark-1.3.0/benchmark/include/benchmark/benchmark.h -+++ b/src/third_party/benchmark-1.3.0/benchmark/include/benchmark/benchmark.h +--- a/src/third_party/benchmark-1.4.1/benchmark/include/benchmark/benchmark.h ++++ b/src/third_party/benchmark-1.4.1/benchmark/include/benchmark/benchmark.h @@ -943,12 +943,10 @@ class Fixture : public internal::Benchmark { this->TearDown(st); } diff --git a/src/third_party/benchmark-1.4.1/patches/0002-SERVER-33491-Fix-benchmark.h-compile-with-fdirective.patch b/src/third_party/benchmark-1.4.1/patches/0002-SERVER-33491-Fix-benchmark.h-compile-with-fdirective.patch new file mode 100644 index 00000000000..d13573118ef --- /dev/null +++ b/src/third_party/benchmark-1.4.1/patches/0002-SERVER-33491-Fix-benchmark.h-compile-with-fdirective.patch @@ -0,0 +1,30 @@ +From 8a275d29b6e17c37ac66380a7689c80e8a52fbb6 Mon Sep 17 00:00:00 2001 +From: Mathias Stearn <mathias@10gen.com> +Date: Mon, 26 Feb 2018 12:24:33 -0500 +Subject: [PATCH] SERVER-33491 Fix benchmark.h compile with -fdirectives-only + +--- + .../benchmark-1.4.1/benchmark/include/benchmark/benchmark.h | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/third_party/benchmark-1.4.1/benchmark/include/benchmark/benchmark.h b/src/third_party/benchmark-1.4.1/benchmark/include/benchmark/benchmark.h +index c8360da..9529faf 100644 +--- a/src/third_party/benchmark-1.4.1/benchmark/include/benchmark/benchmark.h ++++ b/src/third_party/benchmark-1.4.1/benchmark/include/benchmark/benchmark.h +@@ -960,7 +960,12 @@ class Fixture : public internal::Benchmark { + // Check that __COUNTER__ is defined and that __COUNTER__ increases by 1 + // every time it is expanded. X + 1 == X + 0 is used in case X is defined to be + // empty. If X is empty the expression becomes (+1 == +0). +-#if defined(__COUNTER__) && (__COUNTER__ + 1 == __COUNTER__ + 0) ++// ++// MONGODB MODIFICATION: all of our supported compilers support __COUNTER__ so we don't need to test ++// for it here. This test interferes with -E -fdirectives-only since it is illegal to use ++// __COUNTER__ in an #if clause with that flag because its value could change between the partial ++// preprocessing and the compile phases. ++#if true // defined(__COUNTER__) && (__COUNTER__ + 1 == __COUNTER__ + 0) + #define BENCHMARK_PRIVATE_UNIQUE_ID __COUNTER__ + #else + #define BENCHMARK_PRIVATE_UNIQUE_ID __LINE__ +-- +2.10.1.windows.1 + diff --git a/src/third_party/scripts/benchmark_get_sources.sh b/src/third_party/scripts/benchmark_get_sources.sh index 6a3ef4e73d5..c185669e979 100755 --- a/src/third_party/scripts/benchmark_get_sources.sh +++ b/src/third_party/scripts/benchmark_get_sources.sh @@ -1,6 +1,6 @@ #!/bin/bash # This script downloads and imports Google Benchmark. -# It can be run on Linux or Mac OS X. +# It can be run on Linux, Mac OS X or Windows WSL. # Actual integration into the build system is not done by this script. # # Turn on strict error checking, like perl use 'strict' @@ -12,20 +12,41 @@ if [ "$#" -ne 0 ]; then exit 1 fi -VERSION=1.3.0 +GIT_EXE=git +if grep -q Microsoft /proc/version; then + GIT_EXE=git.exe +fi + NAME=benchmark -SRC_ROOT=$(mktemp -d /tmp/benchmark.XXXXXX) -#trap "rm -rf $SRC_ROOT" EXIT +VERSION=1.4.1 +if grep -q Microsoft /proc/version; then + SRC_ROOT=$(wslpath -u $(powershell.exe -Command "Get-ChildItem Env:TEMP | Get-Content | Write-Host")) + SRC_ROOT+="$(mktemp -u /benchmark.XXXXXX)" + mkdir -p $SRC_ROOT +else + SRC_ROOT=$(mktemp -d /tmp/benchmark.XXXXXX) +fi + SRC=${SRC_ROOT}/${NAME}-${VERSION} -DEST_DIR=$(git rev-parse --show-toplevel)/src/third_party/$NAME-$VERSION -PATCH_DIR=$(git rev-parse --show-toplevel)/src/third_party/$NAME-$VERSION/patches +CLONE_DEST=$SRC +if grep -q Microsoft /proc/version; then + CLONE_DEST=$(wslpath -m $SRC) +fi +DEST_DIR=$($GIT_EXE rev-parse --show-toplevel)/src/third_party/$NAME-$VERSION +PATCH_DIR=$($GIT_EXE rev-parse --show-toplevel)/src/third_party/$NAME-$VERSION/patches +if grep -q Microsoft /proc/version; then + DEST_DIR=$(wslpath -u "$DEST_DIR") + PATCH_DIR=$(wslpath -w $(wslpath -u "$PATCH_DIR")) +fi + +echo "dest: $DEST_DIR" +echo "patch: $PATCH_DIR" if [ ! -d $SRC ]; then - git clone git@github.com:google/benchmark.git $SRC + $GIT_EXE clone git@github.com:google/benchmark.git $CLONE_DEST pushd $SRC - git checkout v$VERSION - git am $PATCH_DIR/*.patch + $GIT_EXE checkout v$VERSION popd fi |