Merge to upstream r350972.
Test: ./run_tests.py --bitness 32 Test: ./run_tests.py --bitness 64 Test: ./run_tests.py --bitness 64 --host Bug: None Change-Id: I96552544c8305853be519855982caf716930519e
This commit is contained in:
180
utils/ci/macos-backdeployment.sh
Executable file
180
utils/ci/macos-backdeployment.sh
Executable file
@@ -0,0 +1,180 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -ue
|
||||
|
||||
function usage() {
|
||||
cat <<EOM
|
||||
$(basename ${0}) [-h|--help] --libcxx-root <LIBCXX-ROOT> --libcxxabi-root <LIBCXXABI-ROOT> --std <STD> --arch <ARCHITECTURE> --deployment-target <TARGET> --sdk-version <SDK-VERSION> [--lit-args <ARGS...>]
|
||||
|
||||
This script is used to continually test the back-deployment use case of libc++ and libc++abi on MacOS.
|
||||
|
||||
--libcxx-root Full path to the root of the libc++ repository to test.
|
||||
--libcxxabi-root Full path to the root of the libc++abi repository to test.
|
||||
--std Version of the C++ Standard to run the tests under (c++03, c++11, etc..).
|
||||
--arch Architecture to build the tests for (32, 64).
|
||||
--deployment-target The deployment target to run the tests for. This should be a version number of MacOS (e.g. 10.12). All MacOS versions until and including 10.7 are supported.
|
||||
--sdk-version The version of the SDK to test with. This should be a version number of MacOS (e.g. 10.12). We'll link against the libc++ dylib in that SDK, but we'll run against the one on the given deployment target.
|
||||
[--lit-args] Additional arguments to pass to lit (optional). If there are multiple arguments, quote them to pass them as a single argument to this script.
|
||||
[--no-cleanup] Do not cleanup the temporary directory that was used for testing at the end. This can be useful to debug failures. Make sure to clean up manually after.
|
||||
[-h, --help] Print this help.
|
||||
EOM
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--libcxx-root)
|
||||
LIBCXX_ROOT="${2}"
|
||||
if [[ ! -d "${LIBCXX_ROOT}" ]]; then
|
||||
echo "--libcxx-root '${LIBCXX_ROOT}' is not a valid directory"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
shift; shift
|
||||
;;
|
||||
--libcxxabi-root)
|
||||
LIBCXXABI_ROOT="${2}"
|
||||
if [[ ! -d "${LIBCXXABI_ROOT}" ]]; then
|
||||
echo "--libcxxabi-root '${LIBCXXABI_ROOT}' is not a valid directory"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
shift; shift
|
||||
;;
|
||||
--std)
|
||||
STD="${2}"
|
||||
shift; shift
|
||||
;;
|
||||
--arch)
|
||||
ARCH="${2}"
|
||||
shift; shift
|
||||
;;
|
||||
--deployment-target)
|
||||
DEPLOYMENT_TARGET="${2}"
|
||||
shift; shift
|
||||
;;
|
||||
--sdk-version)
|
||||
MACOS_SDK_VERSION="${2}"
|
||||
shift; shift
|
||||
;;
|
||||
--lit-args)
|
||||
ADDITIONAL_LIT_ARGS="${2}"
|
||||
shift; shift
|
||||
;;
|
||||
--no-cleanup)
|
||||
NO_CLEANUP=""
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "${1} is not a supported argument"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z ${LIBCXX_ROOT+x} ]]; then echo "--libcxx-root is a required parameter"; usage; exit 1; fi
|
||||
if [[ -z ${LIBCXXABI_ROOT+x} ]]; then echo "--libcxxabi-root is a required parameter"; usage; exit 1; fi
|
||||
if [[ -z ${STD+x} ]]; then echo "--std is a required parameter"; usage; exit 1; fi
|
||||
if [[ -z ${ARCH+x} ]]; then echo "--arch is a required parameter"; usage; exit 1; fi
|
||||
if [[ -z ${DEPLOYMENT_TARGET+x} ]]; then echo "--deployment-target is a required parameter"; usage; exit 1; fi
|
||||
if [[ -z ${MACOS_SDK_VERSION+x} ]]; then echo "--sdk-version is a required parameter"; usage; exit 1; fi
|
||||
if [[ -z ${ADDITIONAL_LIT_ARGS+x} ]]; then ADDITIONAL_LIT_ARGS=""; fi
|
||||
|
||||
|
||||
TEMP_DIR="$(mktemp -d)"
|
||||
echo "Created temporary directory ${TEMP_DIR}"
|
||||
function cleanup {
|
||||
if [[ -z ${NO_CLEANUP+x} ]]; then
|
||||
echo "Removing temporary directory ${TEMP_DIR}"
|
||||
rm -rf "${TEMP_DIR}"
|
||||
else
|
||||
echo "Temporary directory is at '${TEMP_DIR}', make sure to clean it up yourself"
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
|
||||
LLVM_ROOT="${TEMP_DIR}/llvm"
|
||||
LIBCXX_BUILD_DIR="${TEMP_DIR}/libcxx-build"
|
||||
LIBCXX_INSTALL_DIR="${TEMP_DIR}/libcxx-install"
|
||||
LIBCXXABI_BUILD_DIR="${TEMP_DIR}/libcxxabi-build"
|
||||
LIBCXXABI_INSTALL_DIR="${TEMP_DIR}/libcxxabi-install"
|
||||
|
||||
PREVIOUS_DYLIBS_URL="http://lab.llvm.org:8080/roots/libcxx-roots.tar.gz"
|
||||
LLVM_TARBALL_URL="https://github.com/llvm-mirror/llvm/archive/master.tar.gz"
|
||||
export CC="$(xcrun --find clang)"
|
||||
export CXX="$(xcrun --find clang++)"
|
||||
|
||||
|
||||
echo "@@@ Downloading LLVM tarball of master (only used for CMake configuration) @@@"
|
||||
mkdir "${LLVM_ROOT}"
|
||||
curl -L "${LLVM_TARBALL_URL}" | tar -xz --strip-components=1 -C "${LLVM_ROOT}"
|
||||
echo "@@@@@@"
|
||||
|
||||
|
||||
echo "@@@ Configuring architecture-related stuff @@@"
|
||||
if [[ "${ARCH}" == "64" ]]; then CMAKE_ARCH_STRING="x86_64"; else CMAKE_ARCH_STRING="i386"; fi
|
||||
if [[ "${ARCH}" == "64" ]]; then LIT_ARCH_STRING=""; else LIT_ARCH_STRING="--param=enable_32bit=true"; fi
|
||||
echo "@@@@@@"
|
||||
|
||||
|
||||
echo "@@@ Configuring CMake for libc++ @@@"
|
||||
mkdir -p "${LIBCXX_BUILD_DIR}"
|
||||
(cd "${LIBCXX_BUILD_DIR}" &&
|
||||
xcrun cmake "${LIBCXX_ROOT}" -GNinja \
|
||||
-DLLVM_PATH="${LLVM_ROOT}" \
|
||||
-DCMAKE_INSTALL_PREFIX="${LIBCXX_INSTALL_DIR}" \
|
||||
-DCMAKE_OSX_ARCHITECTURES="${CMAKE_ARCH_STRING}"
|
||||
)
|
||||
echo "@@@@@@"
|
||||
|
||||
|
||||
echo "@@@ Configuring CMake for libc++abi @@@"
|
||||
mkdir -p "${LIBCXXABI_BUILD_DIR}"
|
||||
(cd "${LIBCXXABI_BUILD_DIR}" &&
|
||||
xcrun cmake "${LIBCXXABI_ROOT}" -GNinja \
|
||||
-DLIBCXXABI_LIBCXX_PATH="${LIBCXX_ROOT}" \
|
||||
-DLLVM_PATH="${LLVM_ROOT}" \
|
||||
-DCMAKE_INSTALL_PREFIX="${LIBCXXABI_INSTALL_DIR}" \
|
||||
-DCMAKE_OSX_ARCHITECTURES="${CMAKE_ARCH_STRING}"
|
||||
)
|
||||
echo "@@@@@@"
|
||||
|
||||
|
||||
echo "@@@ Installing the latest libc++ headers @@@"
|
||||
ninja -C "${LIBCXX_BUILD_DIR}" install-cxx-headers
|
||||
echo "@@@@@@"
|
||||
|
||||
|
||||
echo "@@@ Downloading dylibs for older deployment targets @@@"
|
||||
# TODO: The tarball should contain libc++abi.dylib too, we shouldn't be relying on the system's
|
||||
# TODO: We should also link against the libc++abi.dylib that was shipped in the SDK
|
||||
PREVIOUS_DYLIBS_DIR="${TEMP_DIR}/libcxx-dylibs"
|
||||
mkdir "${PREVIOUS_DYLIBS_DIR}"
|
||||
curl "${PREVIOUS_DYLIBS_URL}" | tar -xz --strip-components=1 -C "${PREVIOUS_DYLIBS_DIR}"
|
||||
LIBCXX_ON_DEPLOYMENT_TARGET="${PREVIOUS_DYLIBS_DIR}/macOS/${DEPLOYMENT_TARGET}/libc++.dylib"
|
||||
LIBCXXABI_ON_DEPLOYMENT_TARGET="/usr/lib/libc++abi.dylib"
|
||||
LIBCXX_IN_SDK="${PREVIOUS_DYLIBS_DIR}/macOS/${MACOS_SDK_VERSION}/libc++.dylib"
|
||||
echo "@@@@@@"
|
||||
|
||||
|
||||
# TODO: We need to also run the tests for libc++abi.
|
||||
# TODO: Make sure lit will actually run against the libc++abi we specified
|
||||
echo "@@@ Running tests for libc++ @@@"
|
||||
"${LIBCXX_BUILD_DIR}/bin/llvm-lit" -sv "${LIBCXX_ROOT}/test" \
|
||||
--param=enable_experimental=false \
|
||||
--param=enable_filesystem=false \
|
||||
${LIT_ARCH_STRING} \
|
||||
--param=cxx_under_test="${CXX}" \
|
||||
--param=cxx_headers="${LIBCXX_INSTALL_DIR}/include/c++/v1" \
|
||||
--param=std="${STD}" \
|
||||
--param=platform="macosx${DEPLOYMENT_TARGET}" \
|
||||
--param=cxx_runtime_root="$(dirname "${LIBCXX_ON_DEPLOYMENT_TARGET}")" \
|
||||
--param=abi_library_path="$(dirname "${LIBCXXABI_ON_DEPLOYMENT_TARGET}")" \
|
||||
--param=use_system_cxx_lib="$(dirname "${LIBCXX_IN_SDK}")" \
|
||||
${ADDITIONAL_LIT_ARGS}
|
||||
echo "@@@@@@"
|
||||
153
utils/ci/macos-trunk.sh
Executable file
153
utils/ci/macos-trunk.sh
Executable file
@@ -0,0 +1,153 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -ue
|
||||
|
||||
function usage() {
|
||||
cat <<EOM
|
||||
$(basename ${0}) [-h|--help] --libcxx-root <LIBCXX-ROOT> --libcxxabi-root <LIBCXXABI-ROOT> --std <STD> --arch <ARCHITECTURE> [--lit-args <ARGS...>]
|
||||
|
||||
This script is used to continually test libc++ and libc++abi trunk on MacOS.
|
||||
|
||||
--libcxx-root Full path to the root of the libc++ repository to test.
|
||||
--libcxxabi-root Full path to the root of the libc++abi repository to test.
|
||||
--std Version of the C++ Standard to run the tests under (c++03, c++11, etc..).
|
||||
--arch Architecture to build the tests for (32, 64).
|
||||
[--lit-args] Additional arguments to pass to lit (optional). If there are multiple arguments, quote them to pass them as a single argument to this script.
|
||||
[--no-cleanup] Do not cleanup the temporary directory that was used for testing at the end. This can be useful to debug failures. Make sure to clean up manually after.
|
||||
[-h, --help] Print this help.
|
||||
EOM
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--libcxx-root)
|
||||
LIBCXX_ROOT="${2}"
|
||||
if [[ ! -e "${LIBCXX_ROOT}" ]]; then
|
||||
echo "--libcxx-root '${LIBCXX_ROOT}' is not a valid directory"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
shift; shift
|
||||
;;
|
||||
--libcxxabi-root)
|
||||
LIBCXXABI_ROOT="${2}"
|
||||
if [[ ! -e "${LIBCXXABI_ROOT}" ]]; then
|
||||
echo "--libcxxabi-root '${LIBCXXABI_ROOT}' is not a valid directory"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
shift; shift
|
||||
;;
|
||||
--std)
|
||||
STD="${2}"
|
||||
shift; shift
|
||||
;;
|
||||
--arch)
|
||||
ARCH="${2}"
|
||||
shift; shift
|
||||
;;
|
||||
--lit-args)
|
||||
ADDITIONAL_LIT_ARGS="${2}"
|
||||
shift; shift
|
||||
;;
|
||||
--no-cleanup)
|
||||
NO_CLEANUP=""
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "${1} is not a supported argument"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z ${LIBCXX_ROOT+x} ]]; then echo "--libcxx-root is a required parameter"; usage; exit 1; fi
|
||||
if [[ -z ${LIBCXXABI_ROOT+x} ]]; then echo "--libcxxabi-root is a required parameter"; usage; exit 1; fi
|
||||
if [[ -z ${STD+x} ]]; then echo "--std is a required parameter"; usage; exit 1; fi
|
||||
if [[ -z ${ARCH+x} ]]; then echo "--arch is a required parameter"; usage; exit 1; fi
|
||||
if [[ -z ${ADDITIONAL_LIT_ARGS+x} ]]; then ADDITIONAL_LIT_ARGS=""; fi
|
||||
|
||||
|
||||
TEMP_DIR="$(mktemp -d)"
|
||||
echo "Created temporary directory ${TEMP_DIR}"
|
||||
function cleanup {
|
||||
if [[ -z ${NO_CLEANUP+x} ]]; then
|
||||
echo "Removing temporary directory ${TEMP_DIR}"
|
||||
rm -rf "${TEMP_DIR}"
|
||||
else
|
||||
echo "Temporary directory is at '${TEMP_DIR}', make sure to clean it up yourself"
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
|
||||
LLVM_ROOT="${TEMP_DIR}/llvm"
|
||||
LIBCXX_BUILD_DIR="${TEMP_DIR}/libcxx-build"
|
||||
LIBCXX_INSTALL_DIR="${TEMP_DIR}/libcxx-install"
|
||||
LIBCXXABI_BUILD_DIR="${TEMP_DIR}/libcxxabi-build"
|
||||
LIBCXXABI_INSTALL_DIR="${TEMP_DIR}/libcxxabi-install"
|
||||
|
||||
LLVM_TARBALL_URL="https://github.com/llvm-mirror/llvm/archive/master.tar.gz"
|
||||
export CC="$(xcrun --find clang)"
|
||||
export CXX="$(xcrun --find clang++)"
|
||||
|
||||
|
||||
echo "@@@ Downloading LLVM tarball of master (only used for CMake configuration) @@@"
|
||||
mkdir "${LLVM_ROOT}"
|
||||
curl -L "${LLVM_TARBALL_URL}" | tar -xz --strip-components=1 -C "${LLVM_ROOT}"
|
||||
echo "@@@@@@"
|
||||
|
||||
|
||||
echo "@@@ Setting up LIT flags @@@"
|
||||
LIT_FLAGS="-sv --param=std=${STD} ${ADDITIONAL_LIT_ARGS}"
|
||||
if [[ "${ARCH}" == "32" ]]; then
|
||||
LIT_FLAGS+=" --param=enable_32bit=true"
|
||||
fi
|
||||
echo "@@@@@@"
|
||||
|
||||
|
||||
echo "@@@ Configuring CMake for libc++ @@@"
|
||||
mkdir -p "${LIBCXX_BUILD_DIR}"
|
||||
(cd "${LIBCXX_BUILD_DIR}" &&
|
||||
xcrun cmake "${LIBCXX_ROOT}" -GNinja \
|
||||
-DLLVM_PATH="${LLVM_ROOT}" \
|
||||
-DCMAKE_INSTALL_PREFIX="${LIBCXX_INSTALL_DIR}" \
|
||||
-DLLVM_LIT_ARGS="${LIT_FLAGS}" \
|
||||
-DCMAKE_OSX_ARCHITECTURES="i386;x86_64" # Build a universal dylib
|
||||
)
|
||||
echo "@@@@@@"
|
||||
|
||||
|
||||
echo "@@@ Configuring CMake for libc++abi @@@"
|
||||
mkdir -p "${LIBCXXABI_BUILD_DIR}"
|
||||
(cd "${LIBCXXABI_BUILD_DIR}" &&
|
||||
xcrun cmake "${LIBCXXABI_ROOT}" -GNinja \
|
||||
-DLIBCXXABI_LIBCXX_PATH="${LIBCXX_ROOT}" \
|
||||
-DLLVM_PATH="${LLVM_ROOT}" \
|
||||
-DCMAKE_INSTALL_PREFIX="${LIBCXXABI_INSTALL_DIR}" \
|
||||
-DLLVM_LIT_ARGS="${LIT_FLAGS}" \
|
||||
-DCMAKE_OSX_ARCHITECTURES="i386;x86_64" # Build a universal dylib
|
||||
)
|
||||
echo "@@@@@@"
|
||||
|
||||
|
||||
echo "@@@ Building libc++.dylib and libc++abi.dylib from sources (just to make sure it works) @@@"
|
||||
ninja -C "${LIBCXX_BUILD_DIR}" install-cxx
|
||||
ninja -C "${LIBCXXABI_BUILD_DIR}" install-cxxabi
|
||||
echo "@@@@@@"
|
||||
|
||||
|
||||
echo "@@@ Running tests for libc++ @@@"
|
||||
# TODO: We should run check-cxx-abilist too
|
||||
ninja -C "${LIBCXX_BUILD_DIR}" check-cxx
|
||||
echo "@@@@@@"
|
||||
|
||||
|
||||
echo "@@@ Running tests for libc++abi @@@"
|
||||
ninja -C "${LIBCXXABI_BUILD_DIR}" check-cxxabi
|
||||
echo "@@@@@@"
|
||||
@@ -109,5 +109,7 @@ RUN apt-get install -y --no-install-recommends \
|
||||
python \
|
||||
buildbot-slave
|
||||
|
||||
ADD scripts /libcxx-scripts/
|
||||
RUN /libcxx-scripts/install_clang_packages.sh
|
||||
ADD scripts/install_clang_packages.sh /tmp/install_clang_packages.sh
|
||||
RUN /tmp/install_clang_packages.sh && rm /tmp/install_clang_packages.sh
|
||||
|
||||
RUN git clone https://git.llvm.org/git/libcxx.git /libcxx
|
||||
|
||||
8
utils/docker/scripts/docker_start_buildbots.sh
Executable file
8
utils/docker/scripts/docker_start_buildbots.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
set -x
|
||||
|
||||
# Update the libc++ sources in the image in order to use the most recent version of
|
||||
# run_buildbots.sh
|
||||
cd /libcxx
|
||||
git pull
|
||||
/libcxx/utils/docker/scripts/run_buildbot.sh "$@"
|
||||
@@ -12,6 +12,13 @@ mkdir -p $BOT_DIR
|
||||
apt-get update -y
|
||||
apt-get upgrade -y
|
||||
|
||||
# FIXME(EricWF): Remove this hack. It's only in place to temporarily fix linking libclang_rt from the
|
||||
# debian packages.
|
||||
# WARNING: If you're not a buildbot, DO NOT RUN!
|
||||
apt-get install lld-8
|
||||
rm /usr/bin/ld
|
||||
ln -s /usr/bin/lld-8 /usr/bin/ld
|
||||
|
||||
systemctl set-property buildslave.service TasksMax=100000
|
||||
|
||||
buildslave stop $BOT_DIR
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
licenses(["notice"])
|
||||
|
||||
config_setting(
|
||||
name = "windows",
|
||||
values = {
|
||||
"cpu": "x64_windows",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "benchmark",
|
||||
srcs = glob(
|
||||
[
|
||||
"src/*.cc",
|
||||
"src/*.h",
|
||||
],
|
||||
exclude = ["src/benchmark_main.cc"],
|
||||
),
|
||||
hdrs = ["include/benchmark/benchmark.h"],
|
||||
linkopts = select({
|
||||
":windows": ["-DEFAULTLIB:shlwapi.lib"],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}),
|
||||
strip_include_prefix = "include",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "benchmark_main",
|
||||
srcs = ["src/benchmark_main.cc"],
|
||||
hdrs = ["include/benchmark/benchmark.h"],
|
||||
strip_include_prefix = "include",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [":benchmark"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "benchmark_internal_headers",
|
||||
hdrs = glob(["src/*.h"]),
|
||||
visibility = ["//test:__pkg__"],
|
||||
)
|
||||
@@ -27,6 +27,7 @@ Arne Beer <arne@twobeer.de>
|
||||
Billy Robert O'Neal III <billy.oneal@gmail.com> <bion@microsoft.com>
|
||||
Chris Kennelly <ckennelly@google.com> <ckennelly@ckennelly.com>
|
||||
Christopher Seymour <chris.j.seymour@hotmail.com>
|
||||
Cyrille Faucheux <cyrille.faucheux@gmail.com>
|
||||
David Coeurjolly <david.coeurjolly@liris.cnrs.fr>
|
||||
Deniz Evrenci <denizevrenci@gmail.com>
|
||||
Dominic Hamon <dma@stripysock.com> <dominic@google.com>
|
||||
|
||||
@@ -255,7 +255,7 @@ that might be used to customize high-order term calculation.
|
||||
|
||||
```c++
|
||||
BENCHMARK(BM_StringCompare)->RangeMultiplier(2)
|
||||
->Range(1<<10, 1<<18)->Complexity([](int n)->double{return n; });
|
||||
->Range(1<<10, 1<<18)->Complexity([](int64_t n)->double{return n; });
|
||||
```
|
||||
|
||||
### Templated benchmarks
|
||||
@@ -264,7 +264,7 @@ messages of size `sizeof(v)` `range_x` times. It also outputs throughput in the
|
||||
absence of multiprogramming.
|
||||
|
||||
```c++
|
||||
template <class Q> int BM_Sequential(benchmark::State& state) {
|
||||
template <class Q> void BM_Sequential(benchmark::State& state) {
|
||||
Q q;
|
||||
typename Q::value_type v;
|
||||
for (auto _ : state) {
|
||||
@@ -428,6 +428,26 @@ BENCHMARK(BM_test)->Range(8, 8<<10)->UseRealTime();
|
||||
|
||||
Without `UseRealTime`, CPU time is used by default.
|
||||
|
||||
## Controlling timers
|
||||
Normally, the entire duration of the work loop (`for (auto _ : state) {}`)
|
||||
is measured. But sometimes, it is nessesary to do some work inside of
|
||||
that loop, every iteration, but without counting that time to the benchmark time.
|
||||
That is possible, althought it is not recommended, since it has high overhead.
|
||||
|
||||
```c++
|
||||
static void BM_SetInsert_With_Timer_Control(benchmark::State& state) {
|
||||
std::set<int> data;
|
||||
for (auto _ : state) {
|
||||
state.PauseTiming(); // Stop timers. They will not count until they are resumed.
|
||||
data = ConstructRandomSet(state.range(0)); // Do something that should not be measured
|
||||
state.ResumeTiming(); // And resume timers. They are now counting again.
|
||||
// The rest will be measured.
|
||||
for (int j = 0; j < state.range(1); ++j)
|
||||
data.insert(RandomNumber());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_SetInsert_With_Timer_Control)->Ranges({{1<<10, 8<<10}, {128, 512}});
|
||||
```
|
||||
|
||||
## Manual timing
|
||||
For benchmarking something for which neither CPU time nor real-time are
|
||||
|
||||
@@ -1293,6 +1293,15 @@ struct CPUInfo {
|
||||
BENCHMARK_DISALLOW_COPY_AND_ASSIGN(CPUInfo);
|
||||
};
|
||||
|
||||
//Adding Struct for System Information
|
||||
struct SystemInfo {
|
||||
std::string name;
|
||||
static const SystemInfo& Get();
|
||||
private:
|
||||
SystemInfo();
|
||||
BENCHMARK_DISALLOW_COPY_AND_ASSIGN(SystemInfo);
|
||||
};
|
||||
|
||||
// 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
|
||||
@@ -1302,6 +1311,7 @@ class BenchmarkReporter {
|
||||
public:
|
||||
struct Context {
|
||||
CPUInfo const& cpu_info;
|
||||
SystemInfo const& sys_info;
|
||||
// The number of chars in the longest benchmark name.
|
||||
size_t name_field_width;
|
||||
static const char* executable_name;
|
||||
|
||||
@@ -57,9 +57,9 @@ DEFINE_bool(benchmark_list_tests, false,
|
||||
|
||||
DEFINE_string(benchmark_filter, ".",
|
||||
"A regular expression that specifies the set of benchmarks "
|
||||
"to execute. If this flag is empty, no benchmarks are run. "
|
||||
"If this flag is the string \"all\", all benchmarks linked "
|
||||
"into the process are run.");
|
||||
"to execute. If this flag is empty, or if this flag is the "
|
||||
"string \"all\", all benchmarks linked into the binary are "
|
||||
"run.");
|
||||
|
||||
DEFINE_double(benchmark_min_time, 0.5,
|
||||
"Minimum number of seconds we should run benchmark before "
|
||||
|
||||
@@ -182,14 +182,19 @@ bool BenchmarkFamilies::FindBenchmarks(
|
||||
}
|
||||
}
|
||||
|
||||
instance.name += StrFormat("%d", arg);
|
||||
// we know that the args are always non-negative (see 'AddRange()'),
|
||||
// thus print as 'unsigned'. BUT, do a cast due to the 32-bit builds.
|
||||
instance.name += StrFormat("%lu", static_cast<unsigned long>(arg));
|
||||
++arg_i;
|
||||
}
|
||||
|
||||
if (!IsZero(family->min_time_))
|
||||
instance.name += StrFormat("/min_time:%0.3f", family->min_time_);
|
||||
if (family->iterations_ != 0)
|
||||
instance.name += StrFormat("/iterations:%d", family->iterations_);
|
||||
if (family->iterations_ != 0) {
|
||||
instance.name +=
|
||||
StrFormat("/iterations:%lu",
|
||||
static_cast<unsigned long>(family->iterations_));
|
||||
}
|
||||
if (family->repetitions_ != 0)
|
||||
instance.name += StrFormat("/repeats:%d", family->repetitions_);
|
||||
|
||||
|
||||
@@ -73,8 +73,8 @@ std::string GetBigOString(BigO complexity) {
|
||||
// - time : Vector containing the times for the benchmark tests.
|
||||
// - 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
|
||||
// For a deeper explanation on the algorithm logic, please refer to
|
||||
// https://en.wikipedia.org/wiki/Least_squares#Least_squares,_regression_analysis_and_statistics
|
||||
|
||||
LeastSq MinimalLeastSq(const std::vector<int64_t>& n,
|
||||
const std::vector<double>& time,
|
||||
|
||||
@@ -53,7 +53,7 @@ bool ConsoleReporter::ReportContext(const Context& context) {
|
||||
}
|
||||
|
||||
void ConsoleReporter::PrintHeader(const Run& run) {
|
||||
std::string str = FormatString("%-*s %13s %13s %10s", static_cast<int>(name_field_width_),
|
||||
std::string str = FormatString("%-*s %13s %15s %12s", static_cast<int>(name_field_width_),
|
||||
"Benchmark", "Time", "CPU", "Iterations");
|
||||
if(!run.counters.empty()) {
|
||||
if(output_options_ & OO_Tabular) {
|
||||
@@ -98,6 +98,21 @@ static void IgnoreColorPrint(std::ostream& out, LogColor, const char* fmt,
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
static std::string FormatTime(double time) {
|
||||
// Align decimal places...
|
||||
if (time < 1.0) {
|
||||
return FormatString("%10.3f", time);
|
||||
}
|
||||
if (time < 10.0) {
|
||||
return FormatString("%10.2f", time);
|
||||
}
|
||||
if (time < 100.0) {
|
||||
return FormatString("%10.1f", time);
|
||||
}
|
||||
return FormatString("%10.0f", time);
|
||||
}
|
||||
|
||||
void ConsoleReporter::PrintRunData(const Run& result) {
|
||||
typedef void(PrinterFn)(std::ostream&, LogColor, const char*, ...);
|
||||
auto& Out = GetOutputStream();
|
||||
@@ -117,18 +132,21 @@ void ConsoleReporter::PrintRunData(const Run& result) {
|
||||
|
||||
const double real_time = result.GetAdjustedRealTime();
|
||||
const double cpu_time = result.GetAdjustedCPUTime();
|
||||
const std::string real_time_str = FormatTime(real_time);
|
||||
const std::string cpu_time_str = FormatTime(cpu_time);
|
||||
|
||||
|
||||
if (result.report_big_o) {
|
||||
std::string big_o = GetBigOString(result.complexity);
|
||||
printer(Out, COLOR_YELLOW, "%10.2f %s %10.2f %s ", real_time, big_o.c_str(),
|
||||
printer(Out, COLOR_YELLOW, "%10.2f %-4s %10.2f %-4s ", real_time, big_o.c_str(),
|
||||
cpu_time, big_o.c_str());
|
||||
} else if (result.report_rms) {
|
||||
printer(Out, COLOR_YELLOW, "%10.0f %% %10.0f %% ", real_time * 100,
|
||||
cpu_time * 100);
|
||||
printer(Out, COLOR_YELLOW, "%10.0f %-4s %10.0f %-4s ", real_time * 100, "%",
|
||||
cpu_time * 100, "%");
|
||||
} else {
|
||||
const char* timeLabel = GetTimeUnitString(result.time_unit);
|
||||
printer(Out, COLOR_YELLOW, "%10.0f %s %10.0f %s ", real_time, timeLabel,
|
||||
cpu_time, timeLabel);
|
||||
printer(Out, COLOR_YELLOW, "%s %-4s %s %-4s ", real_time_str.c_str(), timeLabel,
|
||||
cpu_time_str.c_str(), timeLabel);
|
||||
}
|
||||
|
||||
if (!result.report_big_o && !result.report_rms) {
|
||||
|
||||
@@ -77,6 +77,8 @@ bool JSONReporter::ReportContext(const Context& context) {
|
||||
std::string walltime_value = LocalDateTimeString();
|
||||
out << indent << FormatKV("date", walltime_value) << ",\n";
|
||||
|
||||
out << indent << FormatKV("host_name", context.sys_info.name) << ",\n";
|
||||
|
||||
if (Context::executable_name) {
|
||||
// windows uses backslash for its path separator,
|
||||
// which must be escaped in JSON otherwise it blows up conforming JSON
|
||||
|
||||
@@ -79,7 +79,8 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out,
|
||||
// No initializer because it's already initialized to NULL.
|
||||
const char *BenchmarkReporter::Context::executable_name;
|
||||
|
||||
BenchmarkReporter::Context::Context() : cpu_info(CPUInfo::Get()) {}
|
||||
BenchmarkReporter::Context::Context()
|
||||
: cpu_info(CPUInfo::Get()), sys_info(SystemInfo::Get()) {}
|
||||
|
||||
std::string BenchmarkReporter::Run::benchmark_name() const {
|
||||
std::string name = run_name;
|
||||
|
||||
@@ -12,7 +12,11 @@ void AppendHumanReadable(int n, std::string* str);
|
||||
|
||||
std::string HumanReadableNumber(double n, double one_k = 1024.0);
|
||||
|
||||
std::string StrFormat(const char* format, ...);
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 1, 2)))
|
||||
#endif
|
||||
std::string
|
||||
StrFormat(const char* format, ...);
|
||||
|
||||
inline std::ostream& StrCatImp(std::ostream& out) BENCHMARK_NOEXCEPT {
|
||||
return out;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA
|
||||
#include <versionhelpers.h>
|
||||
#include <windows.h>
|
||||
#include <codecvt>
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#ifndef BENCHMARK_OS_FUCHSIA
|
||||
@@ -52,6 +53,7 @@
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <locale>
|
||||
|
||||
#include "check.h"
|
||||
#include "cycleclock.h"
|
||||
@@ -366,6 +368,35 @@ std::vector<CPUInfo::CacheInfo> GetCacheSizes() {
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string GetSystemName() {
|
||||
#if defined(BENCHMARK_OS_WINDOWS)
|
||||
std::string str;
|
||||
const unsigned COUNT = MAX_COMPUTERNAME_LENGTH+1;
|
||||
TCHAR hostname[COUNT] = {'\0'};
|
||||
DWORD DWCOUNT = COUNT;
|
||||
if (!GetComputerName(hostname, &DWCOUNT))
|
||||
return std::string("");
|
||||
#ifndef UNICODE
|
||||
str = std::string(hostname, DWCOUNT);
|
||||
#else
|
||||
//Using wstring_convert, Is deprecated in C++17
|
||||
using convert_type = std::codecvt_utf8<wchar_t>;
|
||||
std::wstring_convert<convert_type, wchar_t> converter;
|
||||
std::wstring wStr(hostname, DWCOUNT);
|
||||
str = converter.to_bytes(wStr);
|
||||
#endif
|
||||
return str;
|
||||
#else // defined(BENCHMARK_OS_WINDOWS)
|
||||
#ifdef BENCHMARK_OS_MACOSX //Mac Doesnt have HOST_NAME_MAX defined
|
||||
#define HOST_NAME_MAX 64
|
||||
#endif
|
||||
char hostname[HOST_NAME_MAX];
|
||||
int retVal = gethostname(hostname, HOST_NAME_MAX);
|
||||
if (retVal != 0) return std::string("");
|
||||
return std::string(hostname);
|
||||
#endif // Catch-all POSIX block.
|
||||
}
|
||||
|
||||
int GetNumCPUs() {
|
||||
#ifdef BENCHMARK_HAS_SYSCTL
|
||||
int NumCPU = -1;
|
||||
@@ -609,4 +640,11 @@ CPUInfo::CPUInfo()
|
||||
scaling_enabled(CpuScalingEnabled(num_cpus)),
|
||||
load_avg(GetLoadAvg()) {}
|
||||
|
||||
|
||||
const SystemInfo& SystemInfo::Get() {
|
||||
static const SystemInfo* info = new SystemInfo();
|
||||
return *info;
|
||||
}
|
||||
|
||||
SystemInfo::SystemInfo() : name(GetSystemName()) {}
|
||||
} // end namespace benchmark
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <streambuf>
|
||||
|
||||
@@ -38,17 +39,18 @@ SubMap& GetSubstitutions() {
|
||||
// Don't use 'dec_re' from header because it may not yet be initialized.
|
||||
// clang-format off
|
||||
static std::string safe_dec_re = "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?";
|
||||
static std::string time_re = "([0-9]+[.])?[0-9]+";
|
||||
static SubMap map = {
|
||||
{"%float", "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?"},
|
||||
// human-readable float
|
||||
{"%hrfloat", "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?[kMGTPEZYmunpfazy]?"},
|
||||
{"%int", "[ ]*[0-9]+"},
|
||||
{" %s ", "[ ]+"},
|
||||
{"%time", "[ ]*[0-9]+ ns"},
|
||||
{"%console_report", "[ ]*[0-9]+ ns [ ]*[0-9]+ ns [ ]*[0-9]+"},
|
||||
{"%console_time_only_report", "[ ]*[0-9]+ ns [ ]*[0-9]+ ns"},
|
||||
{"%console_us_report", "[ ]*[0-9]+ us [ ]*[0-9]+ us [ ]*[0-9]+"},
|
||||
{"%console_us_time_only_report", "[ ]*[0-9]+ us [ ]*[0-9]+ us"},
|
||||
{"%time", "[ ]*" + time_re + "[ ]+ns"},
|
||||
{"%console_report", "[ ]*" + time_re + "[ ]+ns [ ]*" + time_re + "[ ]+ns [ ]*[0-9]+"},
|
||||
{"%console_time_only_report", "[ ]*" + time_re + "[ ]+ns [ ]*" + time_re + "[ ]+ns"},
|
||||
{"%console_us_report", "[ ]*" + time_re + "[ ]+us [ ]*" + time_re + "[ ]+us [ ]*[0-9]+"},
|
||||
{"%console_us_time_only_report", "[ ]*" + time_re + "[ ]+us [ ]*" + time_re + "[ ]+us"},
|
||||
{"%csv_header",
|
||||
"name,iterations,real_time,cpu_time,time_unit,bytes_per_second,"
|
||||
"items_per_second,label,error_occurred,error_message"},
|
||||
@@ -207,7 +209,7 @@ void ResultsChecker::Add(const std::string& entry_pattern, ResultsCheckFn fn) {
|
||||
void ResultsChecker::CheckResults(std::stringstream& output) {
|
||||
// first reset the stream to the start
|
||||
{
|
||||
auto start = std::ios::streampos(0);
|
||||
auto start = std::stringstream::pos_type(0);
|
||||
// clear before calling tellg()
|
||||
output.clear();
|
||||
// seek to zero only when needed
|
||||
@@ -438,11 +440,50 @@ int SubstrCnt(const std::string& haystack, const std::string& pat) {
|
||||
return count;
|
||||
}
|
||||
|
||||
static char ToHex(int ch) {
|
||||
return ch < 10 ? static_cast<char>('0' + ch)
|
||||
: static_cast<char>('a' + (ch - 10));
|
||||
}
|
||||
|
||||
static char RandomHexChar() {
|
||||
static std::mt19937 rd{std::random_device{}()};
|
||||
static std::uniform_int_distribution<int> mrand{0, 15};
|
||||
return ToHex(mrand(rd));
|
||||
}
|
||||
|
||||
static std::string GetRandomFileName() {
|
||||
std::string model = "test.%%%%%%";
|
||||
for (auto & ch : model) {
|
||||
if (ch == '%')
|
||||
ch = RandomHexChar();
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
static bool FileExists(std::string const& name) {
|
||||
std::ifstream in(name.c_str());
|
||||
return in.good();
|
||||
}
|
||||
|
||||
static std::string GetTempFileName() {
|
||||
// This function attempts to avoid race conditions where two tests
|
||||
// create the same file at the same time. However, it still introduces races
|
||||
// similar to tmpnam.
|
||||
int retries = 3;
|
||||
while (--retries) {
|
||||
std::string name = GetRandomFileName();
|
||||
if (!FileExists(name))
|
||||
return name;
|
||||
}
|
||||
std::cerr << "Failed to create unique temporary file name" << std::endl;
|
||||
std::abort();
|
||||
}
|
||||
|
||||
std::string GetFileReporterOutput(int argc, char* argv[]) {
|
||||
std::vector<char*> new_argv(argv, argv + argc);
|
||||
assert(static_cast<decltype(new_argv)::size_type>(argc) == new_argv.size());
|
||||
|
||||
std::string tmp_file_name = std::tmpnam(nullptr);
|
||||
std::string tmp_file_name = GetTempFileName();
|
||||
std::cout << "Will be using this as the tmp file: " << tmp_file_name << '\n';
|
||||
|
||||
std::string tmp = "--benchmark_out=";
|
||||
|
||||
@@ -23,6 +23,7 @@ static int AddContextCases() {
|
||||
{{"^\\{", MR_Default},
|
||||
{"\"context\":", MR_Next},
|
||||
{"\"date\": \"", MR_Next},
|
||||
{"\"host_name\":", MR_Next},
|
||||
{"\"executable\": \".*(/|\\\\)reporter_output_test(\\.exe)?\",",
|
||||
MR_Next},
|
||||
{"\"num_cpus\": %int,$", MR_Next},
|
||||
@@ -219,6 +220,18 @@ ADD_CASES(TC_JSONOut,
|
||||
{"\"run_type\": \"iteration\",$", MR_Next}});
|
||||
ADD_CASES(TC_CSVOut, {{"^\"BM_arg_names/first:2/5/third:4\",%csv_report$"}});
|
||||
|
||||
// ========================================================================= //
|
||||
// ------------------------ Testing Big Args Output ------------------------ //
|
||||
// ========================================================================= //
|
||||
|
||||
void BM_BigArgs(benchmark::State& state) {
|
||||
for (auto _ : state) {
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_BigArgs)->RangeMultiplier(2)->Range(1U << 30U, 1U << 31U);
|
||||
ADD_CASES(TC_ConsoleOut, {{"^BM_BigArgs/1073741824 %console_report$"},
|
||||
{"^BM_BigArgs/2147483648 %console_report$"}});
|
||||
|
||||
// ========================================================================= //
|
||||
// ----------------------- Testing Complexity Output ----------------------- //
|
||||
// ========================================================================= //
|
||||
@@ -521,7 +534,7 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_UserStats/iterations:5/repeats:3/manual_time [ "
|
||||
{"^BM_UserStats/iterations:5/repeats:3/"
|
||||
"manual_time_median [ ]* 150 ns %time [ ]*3$"},
|
||||
{"^BM_UserStats/iterations:5/repeats:3/"
|
||||
"manual_time_stddev [ ]* 0 ns %time [ ]*3$"},
|
||||
"manual_time_stddev [ ]* 0.000 ns %time [ ]*3$"},
|
||||
{"^BM_UserStats/iterations:5/repeats:3/manual_time_ "
|
||||
"[ ]* 150 ns %time [ ]*3$"}});
|
||||
ADD_CASES(
|
||||
|
||||
@@ -9,56 +9,56 @@ namespace {
|
||||
TEST(StringUtilTest, stoul) {
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(0, benchmark::stoul("0", &pos));
|
||||
EXPECT_EQ(1, pos);
|
||||
EXPECT_EQ(0ul, benchmark::stoul("0", &pos));
|
||||
EXPECT_EQ(1ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(7, benchmark::stoul("7", &pos));
|
||||
EXPECT_EQ(1, pos);
|
||||
EXPECT_EQ(7ul, benchmark::stoul("7", &pos));
|
||||
EXPECT_EQ(1ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(135, benchmark::stoul("135", &pos));
|
||||
EXPECT_EQ(3, pos);
|
||||
EXPECT_EQ(135ul, benchmark::stoul("135", &pos));
|
||||
EXPECT_EQ(3ul, pos);
|
||||
}
|
||||
#if ULONG_MAX == 0xFFFFFFFFul
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(0xFFFFFFFFul, benchmark::stoul("4294967295", &pos));
|
||||
EXPECT_EQ(10, pos);
|
||||
EXPECT_EQ(10ul, pos);
|
||||
}
|
||||
#elif ULONG_MAX == 0xFFFFFFFFFFFFFFFFul
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(0xFFFFFFFFFFFFFFFFul, benchmark::stoul("18446744073709551615", &pos));
|
||||
EXPECT_EQ(20, pos);
|
||||
EXPECT_EQ(20ul, pos);
|
||||
}
|
||||
#endif
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(10, benchmark::stoul("1010", &pos, 2));
|
||||
EXPECT_EQ(4, pos);
|
||||
EXPECT_EQ(10ul, benchmark::stoul("1010", &pos, 2));
|
||||
EXPECT_EQ(4ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(520, benchmark::stoul("1010", &pos, 8));
|
||||
EXPECT_EQ(4, pos);
|
||||
EXPECT_EQ(520ul, benchmark::stoul("1010", &pos, 8));
|
||||
EXPECT_EQ(4ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(1010, benchmark::stoul("1010", &pos, 10));
|
||||
EXPECT_EQ(4, pos);
|
||||
EXPECT_EQ(1010ul, benchmark::stoul("1010", &pos, 10));
|
||||
EXPECT_EQ(4ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(4112, benchmark::stoul("1010", &pos, 16));
|
||||
EXPECT_EQ(4, pos);
|
||||
EXPECT_EQ(4112ul, benchmark::stoul("1010", &pos, 16));
|
||||
EXPECT_EQ(4ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(0xBEEF, benchmark::stoul("BEEF", &pos, 16));
|
||||
EXPECT_EQ(4, pos);
|
||||
EXPECT_EQ(0xBEEFul, benchmark::stoul("BEEF", &pos, 16));
|
||||
EXPECT_EQ(4ul, pos);
|
||||
}
|
||||
{
|
||||
ASSERT_THROW(benchmark::stoul("this is a test"), std::invalid_argument);
|
||||
@@ -69,42 +69,42 @@ TEST(StringUtilTest, stoi) {
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(0, benchmark::stoi("0", &pos));
|
||||
EXPECT_EQ(1, pos);
|
||||
EXPECT_EQ(1ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(-17, benchmark::stoi("-17", &pos));
|
||||
EXPECT_EQ(3, pos);
|
||||
EXPECT_EQ(3ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(1357, benchmark::stoi("1357", &pos));
|
||||
EXPECT_EQ(4, pos);
|
||||
EXPECT_EQ(4ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(10, benchmark::stoi("1010", &pos, 2));
|
||||
EXPECT_EQ(4, pos);
|
||||
EXPECT_EQ(4ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(520, benchmark::stoi("1010", &pos, 8));
|
||||
EXPECT_EQ(4, pos);
|
||||
EXPECT_EQ(4ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(1010, benchmark::stoi("1010", &pos, 10));
|
||||
EXPECT_EQ(4, pos);
|
||||
EXPECT_EQ(4ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(4112, benchmark::stoi("1010", &pos, 16));
|
||||
EXPECT_EQ(4, pos);
|
||||
EXPECT_EQ(4ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(0xBEEF, benchmark::stoi("BEEF", &pos, 16));
|
||||
EXPECT_EQ(4, pos);
|
||||
EXPECT_EQ(4ul, pos);
|
||||
}
|
||||
{
|
||||
ASSERT_THROW(benchmark::stoi("this is a test"), std::invalid_argument);
|
||||
@@ -115,28 +115,28 @@ TEST(StringUtilTest, stod) {
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(0.0, benchmark::stod("0", &pos));
|
||||
EXPECT_EQ(1, pos);
|
||||
EXPECT_EQ(1ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(-84.0, benchmark::stod("-84", &pos));
|
||||
EXPECT_EQ(3, pos);
|
||||
EXPECT_EQ(3ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(1234.0, benchmark::stod("1234", &pos));
|
||||
EXPECT_EQ(4, pos);
|
||||
EXPECT_EQ(4ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
EXPECT_EQ(1.5, benchmark::stod("1.5", &pos));
|
||||
EXPECT_EQ(3, pos);
|
||||
EXPECT_EQ(3ul, pos);
|
||||
}
|
||||
{
|
||||
size_t pos = 0;
|
||||
/* Note: exactly representable as double */
|
||||
EXPECT_EQ(-1.25e+9, benchmark::stod("-1.25e+9", &pos));
|
||||
EXPECT_EQ(8, pos);
|
||||
EXPECT_EQ(8ul, pos);
|
||||
}
|
||||
{
|
||||
ASSERT_THROW(benchmark::stod("this is a test"), std::invalid_argument);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import unittest
|
||||
"""
|
||||
compare.py - versatile benchmark output compare tool
|
||||
"""
|
||||
@@ -244,9 +245,6 @@ def main():
|
||||
print(ln)
|
||||
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
class TestParser(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.parser = create_parser()
|
||||
@@ -402,7 +400,7 @@ class TestParser(unittest.TestCase):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
#unittest.main()
|
||||
# unittest.main()
|
||||
main()
|
||||
|
||||
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import unittest
|
||||
"""report.py - Utilities for reporting statistics about benchmark results
|
||||
"""
|
||||
import os
|
||||
@@ -270,9 +271,6 @@ def generate_difference_report(
|
||||
# Unit tests
|
||||
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
class TestGetUniqueBenchmarkNames(unittest.TestCase):
|
||||
def load_results(self):
|
||||
import json
|
||||
@@ -290,7 +288,7 @@ class TestGetUniqueBenchmarkNames(unittest.TestCase):
|
||||
'BM_One',
|
||||
'BM_Two',
|
||||
'short', # These two are not sorted
|
||||
'medium', # These two are not sorted
|
||||
'medium', # These two are not sorted
|
||||
]
|
||||
json = self.load_results()
|
||||
output_lines = get_unique_benchmark_names(json)
|
||||
@@ -300,6 +298,7 @@ class TestGetUniqueBenchmarkNames(unittest.TestCase):
|
||||
for i in range(0, len(output_lines)):
|
||||
self.assertEqual(expect_lines[i], output_lines[i])
|
||||
|
||||
|
||||
class TestReportDifference(unittest.TestCase):
|
||||
def load_results(self):
|
||||
import json
|
||||
|
||||
@@ -7,11 +7,13 @@ import subprocess
|
||||
import sys
|
||||
|
||||
# Input file type enumeration
|
||||
IT_Invalid = 0
|
||||
IT_JSON = 1
|
||||
IT_Invalid = 0
|
||||
IT_JSON = 1
|
||||
IT_Executable = 2
|
||||
|
||||
_num_magic_bytes = 2 if sys.platform.startswith('win') else 4
|
||||
|
||||
|
||||
def is_executable_file(filename):
|
||||
"""
|
||||
Return 'True' if 'filename' names a valid file which is likely
|
||||
@@ -46,7 +48,7 @@ def is_json_file(filename):
|
||||
with open(filename, 'r') as f:
|
||||
json.load(f)
|
||||
return True
|
||||
except:
|
||||
except BaseException:
|
||||
pass
|
||||
return False
|
||||
|
||||
@@ -84,6 +86,7 @@ def check_input_file(filename):
|
||||
sys.exit(1)
|
||||
return ftype
|
||||
|
||||
|
||||
def find_benchmark_flag(prefix, benchmark_flags):
|
||||
"""
|
||||
Search the specified list of flags for a flag matching `<prefix><arg>` and
|
||||
@@ -97,6 +100,7 @@ def find_benchmark_flag(prefix, benchmark_flags):
|
||||
result = f[len(prefix):]
|
||||
return result
|
||||
|
||||
|
||||
def remove_benchmark_flags(prefix, benchmark_flags):
|
||||
"""
|
||||
Return a new list containing the specified benchmark_flags except those
|
||||
@@ -105,6 +109,7 @@ def remove_benchmark_flags(prefix, benchmark_flags):
|
||||
assert prefix.startswith('--') and prefix.endswith('=')
|
||||
return [f for f in benchmark_flags if not f.startswith(prefix)]
|
||||
|
||||
|
||||
def load_benchmark_results(fname):
|
||||
"""
|
||||
Read benchmark output from a file and return the JSON object.
|
||||
@@ -129,7 +134,7 @@ def run_benchmark(exe_name, benchmark_flags):
|
||||
thandle, output_name = tempfile.mkstemp()
|
||||
os.close(thandle)
|
||||
benchmark_flags = list(benchmark_flags) + \
|
||||
['--benchmark_out=%s' % output_name]
|
||||
['--benchmark_out=%s' % output_name]
|
||||
|
||||
cmd = [exe_name] + benchmark_flags
|
||||
print("RUNNING: %s" % ' '.join(cmd))
|
||||
@@ -156,4 +161,4 @@ def run_or_load_benchmark(filename, benchmark_flags):
|
||||
elif ftype == IT_Executable:
|
||||
return run_benchmark(filename, benchmark_flags)
|
||||
else:
|
||||
assert False # This branch is unreachable
|
||||
assert False # This branch is unreachable
|
||||
|
||||
@@ -307,6 +307,7 @@ class Configuration(object):
|
||||
self.use_system_cxx_lib = False
|
||||
elif self.use_system_cxx_lib:
|
||||
assert os.path.isdir(self.use_system_cxx_lib), "the specified use_system_cxx_lib parameter (%s) is not a valid directory" % self.use_system_cxx_lib
|
||||
self.use_system_cxx_lib = os.path.abspath(self.use_system_cxx_lib)
|
||||
self.lit_config.note(
|
||||
"inferred use_system_cxx_lib as: %r" % self.use_system_cxx_lib)
|
||||
|
||||
@@ -406,11 +407,10 @@ class Configuration(object):
|
||||
if self.use_deployment:
|
||||
self.add_deployment_feature('with_system_cxx_lib')
|
||||
|
||||
# Configure the availability markup checks features.
|
||||
if self.use_deployment:
|
||||
self.config.available_features.add('availability_markup')
|
||||
self.add_deployment_feature('availability_markup')
|
||||
|
||||
# Configure the availability feature. Availability is only enabled
|
||||
# with libc++, because other standard libraries do not provide
|
||||
# availability markup.
|
||||
if self.use_deployment and self.cxx_stdlib_under_test == 'libc++':
|
||||
self.config.available_features.add('availability')
|
||||
self.add_deployment_feature('availability')
|
||||
|
||||
@@ -487,13 +487,7 @@ class Configuration(object):
|
||||
self.config.available_features.add("objective-c++")
|
||||
|
||||
def configure_compile_flags(self):
|
||||
no_default_flags = self.get_lit_bool('no_default_flags', False)
|
||||
if not no_default_flags:
|
||||
self.configure_default_compile_flags()
|
||||
# This include is always needed so add so add it regardless of
|
||||
# 'no_default_flags'.
|
||||
support_path = os.path.join(self.libcxx_src_root, 'test/support')
|
||||
self.cxx.compile_flags += ['-I' + support_path]
|
||||
self.configure_default_compile_flags()
|
||||
# Configure extra flags
|
||||
compile_flags_str = self.get_lit_conf('compile_flags', '')
|
||||
self.cxx.compile_flags += shlex.split(compile_flags_str)
|
||||
@@ -574,6 +568,10 @@ class Configuration(object):
|
||||
self.cxx.flags += ['-arch', arch]
|
||||
self.cxx.flags += ['-m' + name + '-version-min=' + version]
|
||||
|
||||
# Add includes for support headers used in the tests.
|
||||
support_path = os.path.join(self.libcxx_src_root, 'test/support')
|
||||
self.cxx.compile_flags += ['-I' + support_path]
|
||||
|
||||
# FIXME(EricWF): variant_size.pass.cpp requires a slightly larger
|
||||
# template depth with older Clang versions.
|
||||
self.cxx.addFlagIfSupported('-ftemplate-depth=270')
|
||||
@@ -731,37 +729,33 @@ class Configuration(object):
|
||||
|
||||
|
||||
def configure_link_flags(self):
|
||||
no_default_flags = self.get_lit_bool('no_default_flags', False)
|
||||
if not no_default_flags:
|
||||
# Configure library path
|
||||
self.configure_link_flags_cxx_library_path()
|
||||
self.configure_link_flags_abi_library_path()
|
||||
# Configure library path
|
||||
self.configure_link_flags_cxx_library_path()
|
||||
self.configure_link_flags_abi_library_path()
|
||||
|
||||
# Configure libraries
|
||||
if self.cxx_stdlib_under_test == 'libc++':
|
||||
self.cxx.link_flags += ['-nodefaultlibs']
|
||||
# FIXME: Handle MSVCRT as part of the ABI library handling.
|
||||
if self.is_windows:
|
||||
self.cxx.link_flags += ['-nostdlib']
|
||||
self.configure_link_flags_cxx_library()
|
||||
self.configure_link_flags_abi_library()
|
||||
self.configure_extra_library_flags()
|
||||
elif self.cxx_stdlib_under_test == 'libstdc++':
|
||||
enable_fs = self.get_lit_bool('enable_filesystem',
|
||||
default=False)
|
||||
if enable_fs:
|
||||
self.config.available_features.add('c++experimental')
|
||||
self.cxx.link_flags += ['-lstdc++fs']
|
||||
self.cxx.link_flags += ['-lm', '-pthread']
|
||||
elif self.cxx_stdlib_under_test == 'msvc':
|
||||
# FIXME: Correctly setup debug/release flags here.
|
||||
pass
|
||||
elif self.cxx_stdlib_under_test == 'cxx_default':
|
||||
self.cxx.link_flags += ['-pthread']
|
||||
else:
|
||||
self.lit_config.fatal(
|
||||
'unsupported value for "use_stdlib_type": %s'
|
||||
% use_stdlib_type)
|
||||
# Configure libraries
|
||||
if self.cxx_stdlib_under_test == 'libc++':
|
||||
self.cxx.link_flags += ['-nodefaultlibs']
|
||||
# FIXME: Handle MSVCRT as part of the ABI library handling.
|
||||
if self.is_windows:
|
||||
self.cxx.link_flags += ['-nostdlib']
|
||||
self.configure_link_flags_cxx_library()
|
||||
self.configure_link_flags_abi_library()
|
||||
self.configure_extra_library_flags()
|
||||
elif self.cxx_stdlib_under_test == 'libstdc++':
|
||||
enable_fs = self.get_lit_bool('enable_filesystem',
|
||||
default=False)
|
||||
if enable_fs:
|
||||
self.config.available_features.add('c++experimental')
|
||||
self.cxx.link_flags += ['-lstdc++fs']
|
||||
self.cxx.link_flags += ['-lm', '-pthread']
|
||||
elif self.cxx_stdlib_under_test == 'msvc':
|
||||
# FIXME: Correctly setup debug/release flags here.
|
||||
pass
|
||||
elif self.cxx_stdlib_under_test == 'cxx_default':
|
||||
self.cxx.link_flags += ['-pthread']
|
||||
else:
|
||||
self.lit_config.fatal('invalid stdlib under test')
|
||||
|
||||
link_flags_str = self.get_lit_conf('link_flags', '')
|
||||
self.cxx.link_flags += shlex.split(link_flags_str)
|
||||
|
||||
@@ -144,12 +144,12 @@ class DarwinLocalTI(DefaultTargetInfo):
|
||||
def configure_env(self, env):
|
||||
library_paths = []
|
||||
# Configure the library path for libc++
|
||||
if self.full_config.use_system_cxx_lib:
|
||||
if self.full_config.cxx_runtime_root:
|
||||
library_paths += [self.full_config.cxx_runtime_root]
|
||||
elif self.full_config.use_system_cxx_lib:
|
||||
if (os.path.isdir(str(self.full_config.use_system_cxx_lib))):
|
||||
library_paths += [self.full_config.use_system_cxx_lib]
|
||||
pass
|
||||
elif self.full_config.cxx_runtime_root:
|
||||
library_paths += [self.full_config.cxx_runtime_root]
|
||||
|
||||
# Configure the abi library path
|
||||
if self.full_config.abi_library_root:
|
||||
library_paths += [self.full_config.abi_library_root]
|
||||
@@ -182,6 +182,18 @@ class FreeBSDLocalTI(DefaultTargetInfo):
|
||||
flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt']
|
||||
|
||||
|
||||
class NetBSDLocalTI(DefaultTargetInfo):
|
||||
def __init__(self, full_config):
|
||||
super(NetBSDLocalTI, self).__init__(full_config)
|
||||
|
||||
def add_locale_features(self, features):
|
||||
add_common_locales(features, self.full_config.lit_config)
|
||||
|
||||
def add_cxx_link_flags(self, flags):
|
||||
flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lc++abi',
|
||||
'-lunwind']
|
||||
|
||||
|
||||
class LinuxLocalTI(DefaultTargetInfo):
|
||||
def __init__(self, full_config):
|
||||
super(LinuxLocalTI, self).__init__(full_config)
|
||||
@@ -280,6 +292,7 @@ def make_target_info(full_config):
|
||||
target_system = platform.system()
|
||||
if target_system == 'Darwin': return DarwinLocalTI(full_config)
|
||||
if target_system == 'FreeBSD': return FreeBSDLocalTI(full_config)
|
||||
if target_system == 'NetBSD': return NetBSDLocalTI(full_config)
|
||||
if target_system == 'Linux': return LinuxLocalTI(full_config)
|
||||
if target_system == 'Windows': return WindowsLocalTI(full_config)
|
||||
return DefaultTargetInfo(full_config)
|
||||
|
||||
Reference in New Issue
Block a user