From 398a8ac2e8e0b852fa1568dc1c8ebdfc743a380a Mon Sep 17 00:00:00 2001 From: Raghu Raja Date: Mon, 31 Oct 2022 04:03:59 -0700 Subject: [PATCH] [bazel] Build libpfm as a dependency to allow collection of perf counters (#1408) * Build libpfm as a dependency to allow collection of perf counters This commit builds libpfm using rules_foreign_cc and lets the default build of the benchmark library support perf counter collection without needing additional work from users. Tested with a custom target: ``` bazel run \ --override_repository=com_github_google_benchmark=/home/raghu/benchmark \ -c opt :test-bench -- "--benchmark_perf_counters=INSTRUCTIONS,CYCLES" Using profile: local ---------------------------------------------------------------------- Benchmark Time CPU Iterations UserCounters... ---------------------------------------------------------------------- BM_Test 0.279 ns 0.279 ns 1000000000 CYCLES=1.00888 INSTRUCTIONS=2 ``` Signed-off-by: Raghu Raja * Adding myself to the CONTRIBUTORS file per CLA guidance Enfabrica has already signed a corporate CLA. Signed-off-by: Raghu Raja Signed-off-by: Raghu Raja --- AUTHORS | 1 + BUILD.bazel | 19 ++++++++++++++++++- CONTRIBUTORS | 1 + WORKSPACE | 31 +++++++++++++++++++++++++++++++ docs/perf_counters.md | 13 +++++++------ tools/libpfm.BUILD.bazel | 21 +++++++++++++++++++++ 6 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 tools/libpfm.BUILD.bazel diff --git a/AUTHORS b/AUTHORS index 3f3fd37037..98d2d98b05 100644 --- a/AUTHORS +++ b/AUTHORS @@ -50,6 +50,7 @@ Norman Heino Oleksandr Sochka Ori Livneh Paul Redmond +Raghu Raja Radoslav Yovchev Rainer Orth Roman Lebedev diff --git a/BUILD.bazel b/BUILD.bazel index af18e3d7de..64f86eedc9 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -18,6 +18,14 @@ config_setting( visibility = [":__subpackages__"], ) +config_setting( + name = "perfcounters", + define_values = { + "pfm": "1", + }, + visibility = [":__subpackages__"], +) + cc_library( name = "benchmark", srcs = glob( @@ -41,7 +49,16 @@ cc_library( # Using `defines` (i.e. not `local_defines`) means that no # dependent rules need to bother about defining the macro. linkstatic = True, - defines = ["BENCHMARK_STATIC_DEFINE"], + defines = [ + "BENCHMARK_STATIC_DEFINE", + ] + select({ + ":perfcounters": ["HAVE_LIBPFM"], + "//conditions:default": [], + }), + deps = select({ + ":perfcounters": ["@libpfm//:libpfm"], + "//conditions:default": [], + }), ) cc_library( diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 6fe918ebe5..32ab15bbe0 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -74,6 +74,7 @@ Paul Redmond Pierre Phaneuf Radoslav Yovchev Rainer Orth +Raghu Raja Raul Marin Ray Glover Robert Guo diff --git a/WORKSPACE b/WORKSPACE index 6d1c51a0a6..b468abafd5 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -3,6 +3,27 @@ workspace(name = "com_github_google_benchmark") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") + +http_archive( + name = "bazel_skylib", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.2.1/bazel-skylib-1.2.1.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.2.1/bazel-skylib-1.2.1.tar.gz", + ], + sha256 = "f7be3474d42aae265405a592bb7da8e171919d74c16f082a5457840f06054728", +) + +# https://github.com/bazelbuild/rules_foreign_cc/ +http_archive( + name = "rules_foreign_cc", + sha256 = "bcd0c5f46a49b85b384906daae41d277b3dc0ff27c7c752cc51e43048a58ec83", + strip_prefix = "rules_foreign_cc-0.7.1", + url = "https://github.com/bazelbuild/rules_foreign_cc/archive/0.7.1.tar.gz", +) + +load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies") +rules_foreign_cc_dependencies() + http_archive( name = "com_google_absl", sha256 = "f41868f7a938605c92936230081175d1eae87f6ea2c248f41077c8f88316f111", @@ -16,6 +37,16 @@ git_repository( tag = "release-1.11.0", ) +# Downloaded from v4.9.0 tag at https://sourceforge.net/p/perfmon2/libpfm4/ref/master/tags/ +http_archive( + name = "libpfm", + build_file = "//tools:libpfm.BUILD.bazel", + sha256 = "5da5f8872bde14b3634c9688d980f68bda28b510268723cc12973eedbab9fecc", + type = "tar.gz", + strip_prefix = "libpfm-4.11.0", + urls = ["https://sourceforge.net/projects/perfmon2/files/libpfm4/libpfm-4.11.0.tar.gz/download"], +) + http_archive( name = "pybind11", build_file = "@//bindings/python:pybind11.BUILD", diff --git a/docs/perf_counters.md b/docs/perf_counters.md index 74560e9669..db83145c9a 100644 --- a/docs/perf_counters.md +++ b/docs/perf_counters.md @@ -12,16 +12,17 @@ This feature is available if: * The benchmark is run on an architecture featuring a Performance Monitoring Unit (PMU), * The benchmark is compiled with support for collecting counters. Currently, - this requires [libpfm](http://perfmon2.sourceforge.net/) be available at build - time + this requires [libpfm](http://perfmon2.sourceforge.net/), which is built as a + dependency via Bazel. The feature does not require modifying benchmark code. Counter collection is handled at the boundaries where timer collection is also handled. To opt-in: - -* Install `libpfm4-dev`, e.g. `apt-get install libpfm4-dev`. -* Enable the cmake flag BENCHMARK_ENABLE_LIBPFM. +* If using a Bazel build, add `--define pfm=1` to your buid flags +* If using CMake: + * Install `libpfm4-dev`, e.g. `apt-get install libpfm4-dev`. + * Enable the CMake flag `BENCHMARK_ENABLE_LIBPFM` in `CMakeLists.txt`. To use, pass a comma-separated list of counter names through the `--benchmark_perf_counters` flag. The names are decoded through libpfm - meaning, @@ -31,4 +32,4 @@ mapped by libpfm to platform-specifics - see libpfm The counter values are reported back through the [User Counters](../README.md#custom-counters) mechanism, meaning, they are available in all the formats (e.g. JSON) supported -by User Counters. \ No newline at end of file +by User Counters. diff --git a/tools/libpfm.BUILD.bazel b/tools/libpfm.BUILD.bazel new file mode 100644 index 0000000000..f661064fd5 --- /dev/null +++ b/tools/libpfm.BUILD.bazel @@ -0,0 +1,21 @@ +# Build rule for libpfm, which is required to collect performance counters for +# BENCHMARK_ENABLE_LIBPFM builds. + +load("@rules_foreign_cc//foreign_cc:defs.bzl", "make") + +filegroup( + name = "pfm_srcs", + srcs = glob(["**"]), +) + +make( + name = "libpfm", + lib_source = ":pfm_srcs", + lib_name = "libpfm", + copts = [ + "-Wno-format-truncation", + ], + visibility = [ + "//visibility:public", + ], +)