Index: MicroBenchmarks/XRay/CMakeLists.txt =================================================================== --- MicroBenchmarks/XRay/CMakeLists.txt +++ MicroBenchmarks/XRay/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(ReturnReference) add_subdirectory(FDRMode) +add_subdirectory(ProfilingMode) Index: MicroBenchmarks/XRay/ProfilingMode/CMakeLists.txt =================================================================== --- /dev/null +++ MicroBenchmarks/XRay/ProfilingMode/CMakeLists.txt @@ -0,0 +1,18 @@ +check_cxx_compiler_flag(-fxray-instrument COMPILER_HAS_FXRAY_INSTRUMENT) +check_cxx_compiler_flag(-fxray-modes=xray-profiling + COMPILER_HAS_FXRAY_PROFILING) +if(ARCH STREQUAL "x86" + AND COMPILER_HAS_FXRAY_INSTRUMENT + AND COMPILER_HAS_FXRAY_PROFILING) + list(APPEND CPPFLAGS + -std=c++11 -Wl,--gc-sections + -fxray-instrument -fxray-modes=xray-profiling) + list(APPEND LDFLAGS + -fxray-instrument -fxray-modes=xray-profiling) + llvm_test_run() + llvm_test_executable(deep-call-bench deep-call-bench.cc) + target_link_libraries(deep-call-bench benchmark) + llvm_test_executable(shallow-call-bench shallow-call-bench.cc) + target_link_libraries(shallow-call-bench benchmark) +endif() + Index: MicroBenchmarks/XRay/ProfilingMode/deep-call-bench.cc =================================================================== --- /dev/null +++ MicroBenchmarks/XRay/ProfilingMode/deep-call-bench.cc @@ -0,0 +1,83 @@ +//===- deep-call-bench.cc - XRay Profiling Mode Benchmarks ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These benchmarks measure the cost of XRay profiling mode when enabled. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include "benchmark/benchmark.h" +#include "xray/xray_log_interface.h" + +namespace { + +std::atomic some_global{0}; + +std::atomic some_temporary{0}; + +std::once_flag profiling_init_flag; + +std::atomic go{false}; + +[[clang::xray_never_instrument]] static void profiling_init() { + if (__xray_log_select_mode("xray-profiling") != XRAY_REGISTRATION_OK) { + std::cerr << "Failed selecting 'xray-profiling' mode. Aborting.\n"; + std::abort(); + } + + if (__xray_log_init_mode("xray-profiling", "no_flush=true") != + XRAY_LOG_INITIALIZED) { + std::cerr << "Failed initializing xray-profiling mode. Aborting.\n"; + std::abort(); + }; + + __xray_patch(); + go.store(true, std::memory_order_release); +} + +} // namespace + +#define XRAY_WEAK_NOINLINE \ + [[clang::xray_always_instrument]] __attribute__((weak)) \ + __attribute__((noinline)) + +XRAY_WEAK_NOINLINE void deep8() { + some_global.fetch_add(1, std::memory_order_relaxed); +} +XRAY_WEAK_NOINLINE void deep7() { deep8(); } +XRAY_WEAK_NOINLINE void deep6() { deep7(); } +XRAY_WEAK_NOINLINE void deep5() { deep6(); } +XRAY_WEAK_NOINLINE void deep4() { deep5(); } +XRAY_WEAK_NOINLINE void deep3() { deep4(); } +XRAY_WEAK_NOINLINE void deep2() { deep3(); } +XRAY_WEAK_NOINLINE void deep1() { deep2(); } +XRAY_WEAK_NOINLINE int deep0() { + deep1(); + return some_global.load(std::memory_order_acquire); +} + +[[clang::xray_never_instrument]] static void BM_XRayProfilingDeepCallStack( + benchmark::State &state) { + std::call_once(profiling_init_flag, profiling_init); + + // Spin until we see the flag set. + while (!go.load(std::memory_order_acquire)) + ; + + // Warm up the data structures. + benchmark::DoNotOptimize(some_temporary = deep0()); + + for (auto _ : state) benchmark::DoNotOptimize(some_temporary = deep0()); +} +BENCHMARK(BM_XRayProfilingDeepCallStack)->ThreadRange(1, 32); + +BENCHMARK_MAIN(); Index: MicroBenchmarks/XRay/ProfilingMode/shallow-call-bench.cc =================================================================== --- /dev/null +++ MicroBenchmarks/XRay/ProfilingMode/shallow-call-bench.cc @@ -0,0 +1,71 @@ +//===- profilingmode-bench.cc - XRay Profiling Mode Benchmarks ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These benchmarks measure the cost of XRay profiling mode when enabled. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include "benchmark/benchmark.h" +#include "xray/xray_log_interface.h" + +namespace { + +std::atomic some_global{0}; + +std::atomic some_temporary{0}; + +std::once_flag profiling_init_flag; + +std::atomic go{false}; + +[[clang::xray_never_instrument]] static void profiling_init() { + if (__xray_log_select_mode("xray-profiling") != XRAY_REGISTRATION_OK) { + std::cerr << "Failed selecting 'xray-profiling' mode. Aborting.\n"; + std::abort(); + } + + if (__xray_log_init_mode("xray-profiling", "no_flush=true") != + XRAY_LOG_INITIALIZED) { + std::cerr << "Failed initializing xray-profiling mode. Aborting.\n"; + std::abort(); + }; + + __xray_patch(); + go.store(true, std::memory_order_release); +} + +} // namespace + +#define XRAY_WEAK_NOINLINE \ + [[clang::xray_always_instrument]] __attribute__((weak)) \ + __attribute__((noinline)) + +XRAY_WEAK_NOINLINE int shallow() { + return some_global.fetch_add(1, std::memory_order_acq_rel); +} + +[[clang::xray_never_instrument]] static void BM_XRayProfilingShallowStack( + benchmark::State &state) { + std::call_once(profiling_init_flag, profiling_init); + + while (!go.load(std::memory_order_acquire)) + ; + + // Warm up the data structures. + benchmark::DoNotOptimize(some_temporary = shallow()); + + for (auto _ : state) benchmark::DoNotOptimize(some_temporary = shallow()); +} +BENCHMARK(BM_XRayProfilingShallowStack)->ThreadRange(1, 32); + +BENCHMARK_MAIN();