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,20 @@ +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) + llvm_test_executable(wide-call-bench wide-call-bench.cc) + target_link_libraries(wide-call-bench benchmark) +endif() + Index: MicroBenchmarks/XRay/ProfilingMode/deep-call-bench.cc =================================================================== --- /dev/null +++ MicroBenchmarks/XRay/ProfilingMode/deep-call-bench.cc @@ -0,0 +1,77 @@ +//===- 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{1}; + +std::atomic some_temporary{0}; + +[[clang::xray_never_instrument]] static void profiling_setup() { + 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(); +} + +[[clang::xray_never_instrument]] static void profiling_teardown() { + if (__xray_log_finalize() != XRAY_LOG_FINALIZED) { + std::cerr << "Failed to finalize xray-profiling mode. Aborting.\n"; + std::abort(); + } + + if (__xray_log_flushLog() != XRAY_LOG_FLUSHED) { + std::cerr << "Failed to flush xray-profiling mode. Aborting.\n"; + std::abort(); + } +} + +} // namespace + +[[clang::xray_always_instrument]] __attribute__((weak)) +__attribute__((noinline)) int +deep(int depth) { + if (depth == 0) return some_global.load(std::memory_order_acquire); + return some_global.load(std::memory_order_acquire) + deep(depth - 1); +} + +[[clang::xray_never_instrument]] static void BM_XRayProfilingDeepCallStack( + benchmark::State &state) { + if (state.thread_index == 0) profiling_setup(); + + for (auto _ : state) + benchmark::DoNotOptimize(some_temporary = deep(state.range(0))); + + if (state.thread_index == 0) profiling_teardown(); +} +BENCHMARK(BM_XRayProfilingDeepCallStack) + ->ThreadRange(1, 32) + ->RangeMultiplier(2) + ->Range(4, 128); + +BENCHMARK_MAIN(); Index: MicroBenchmarks/XRay/ProfilingMode/shallow-call-bench.cc =================================================================== --- /dev/null +++ MicroBenchmarks/XRay/ProfilingMode/shallow-call-bench.cc @@ -0,0 +1,74 @@ +//===- shallow-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}; + +[[clang::xray_never_instrument]] static void profiling_setup() { + 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(); +} + +[[clang::xray_never_instrument]] static void profiling_teardown() { + if (__xray_log_finalize() != XRAY_LOG_FINALIZED) { + std::cerr << "Failed to finalize xray-profiling mode. Aborting.\n"; + std::abort(); + } + + if (__xray_log_flushLog() != XRAY_LOG_FLUSHED) { + std::cerr << "Failed to flush xray-profiling mode. Aborting.\n"; + std::abort(); + } +} + +} // 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) { + if (state.thread_index == 0) profiling_setup(); + + for (auto _ : state) benchmark::DoNotOptimize(some_temporary = shallow()); + + if (state.thread_index == 0) profiling_teardown(); +} +BENCHMARK(BM_XRayProfilingShallowStack)->ThreadRange(1, 32); + +BENCHMARK_MAIN(); Index: MicroBenchmarks/XRay/ProfilingMode/wide-call-bench.cc =================================================================== --- /dev/null +++ MicroBenchmarks/XRay/ProfilingMode/wide-call-bench.cc @@ -0,0 +1,127 @@ +//===- wide-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{1}; + +std::atomic some_temporary{0}; + +[[clang::xray_never_instrument]] static void profiling_setup() { + 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(); +} + +[[clang::xray_never_instrument]] static void profiling_teardown() { + if (__xray_log_finalize() != XRAY_LOG_FINALIZED) { + std::cerr << "Failed to finalize xray-profiling mode. Aborting.\n"; + std::abort(); + } + + if (__xray_log_flushLog() != XRAY_LOG_FLUSHED) { + std::cerr << "Failed to flush xray-profiling mode. Aborting.\n"; + std::abort(); + } +} + +} // namespace + +#define XRAY_WEAK_NOINLINE \ + [[clang::xray_always_instrument]] __attribute__((weak)) \ + __attribute__((noinline)) + +XRAY_WEAK_NOINLINE int wide8() { + return some_global.load(std::memory_order_acquire); +} +XRAY_WEAK_NOINLINE int wide7() { + return some_global.load(std::memory_order_acquire); +} +XRAY_WEAK_NOINLINE int wide6() { + return some_global.load(std::memory_order_acquire); +} +XRAY_WEAK_NOINLINE int wide5() { + return some_global.load(std::memory_order_acquire); +} +XRAY_WEAK_NOINLINE int wide4() { + return some_global.load(std::memory_order_acquire); +} +XRAY_WEAK_NOINLINE int wide3() { + return some_global.load(std::memory_order_acquire); +} +XRAY_WEAK_NOINLINE int wide2() { + return some_global.load(std::memory_order_acquire); +} +XRAY_WEAK_NOINLINE int wide1() { + return some_global.load(std::memory_order_acquire); +} +XRAY_WEAK_NOINLINE int call(int depth, int width) { + if (depth == 0) return some_global.load(std::memory_order_acquire); + + auto val = 0; + switch (width) { + default: + case 8: + val += wide8(); + case 7: + val += wide7(); + case 6: + val += wide6(); + case 5: + val += wide5(); + case 4: + val += wide4(); + case 3: + val += wide3(); + case 2: + val += wide2(); + case 1: + val += wide1(); + } + + return some_global.load(std::memory_order_acquire) + val + + call(depth - 1, width); +} + +[[clang::xray_never_instrument]] static void BM_XRayProfilingDeepCallStack( + benchmark::State &state) { + if (state.thread_index == 0) profiling_setup(); + + for (auto _ : state) + benchmark::DoNotOptimize(some_temporary = + call(state.range(0), state.range(1))); + + if (state.thread_index == 0) profiling_teardown(); +} +BENCHMARK(BM_XRayProfilingDeepCallStack) + ->ThreadRange(1, 32) + ->RangeMultiplier(2) + ->Ranges({{4, 128}, {1, 8}}); + +BENCHMARK_MAIN();