Pass State to ProfilerManager via new WithState hooks (#2234) (#2313)
* Pass State to ProfilerManager via new WithState hooks (#2234)
* Include state.h instead of forward-declaring State; fix clang-format
---------
Co-authored-by: dominic <510002+dmah42@users.noreply.github.com>
diff --git a/AUTHORS b/AUTHORS
index 65cad40..4a14b98 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -38,6 +38,7 @@
GergÅ‘ Szitár <szitar.gergo@gmail.com>
Google Inc.
Haihan Jiang <haihanj99@gmail.com>
+Harsh Chaturvedi <chaturvediharsh123@gmail.com>
Henrique Bucher <hbucher@gmail.com>
International Business Machines Corporation
Ismael Jimenez Martinez <ismael.jimenez.martinez@gmail.com>
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index a77788f..74e5fe9 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -59,6 +59,7 @@
GergÅ‘ Szitár <szitar.gergo@gmail.com>
Haihan Jiang <haihanj99@gmail.com>
Hannes Hauswedell <h2@fsfe.org>
+Harsh Chaturvedi <chaturvediharsh123@gmail.com>
Henrique Bucher <hbucher@gmail.com>
Ismael Jimenez Martinez <ismael.jimenez.martinez@gmail.com>
Iakov Sergeev <yahontu@gmail.com>
diff --git a/docs/user_guide.md b/docs/user_guide.md
index cd96baf..9e46a51 100644
--- a/docs/user_guide.md
+++ b/docs/user_guide.md
@@ -1628,6 +1628,11 @@
end of a separate benchmark run to allow user code to collect and report
user-provided profile metrics.
+If your profiler needs the current benchmark name or other run state, override
+`ProfilerManager::AfterSetupStartWithState(const State&)` and
+`ProfilerManager::BeforeTeardownStopWithState(const State&)`. The legacy
+no-argument hooks still work and remain the fallback.
+
Output collected from this profiling run must be reported separately.
<a name="using-register-benchmark" />
diff --git a/include/benchmark/managers.h b/include/benchmark/managers.h
index e8b6cd4..963bf58 100644
--- a/include/benchmark/managers.h
+++ b/include/benchmark/managers.h
@@ -20,6 +20,7 @@
#include <limits>
#include "benchmark/macros.h"
+#include "benchmark/state.h"
#include "benchmark/types.h"
namespace benchmark {
@@ -54,8 +55,12 @@
class ProfilerManager {
public:
virtual ~ProfilerManager() {}
- virtual void AfterSetupStart() = 0;
- virtual void BeforeTeardownStop() = 0;
+ virtual void AfterSetupStart() {}
+ virtual void BeforeTeardownStop() {}
+ virtual void AfterSetupStartWithState(const State&) { AfterSetupStart(); }
+ virtual void BeforeTeardownStopWithState(const State&) {
+ BeforeTeardownStop();
+ }
};
BENCHMARK_EXPORT
diff --git a/src/benchmark.cc b/src/benchmark.cc
index 5d1e7e9..4a6789f 100644
--- a/src/benchmark.cc
+++ b/src/benchmark.cc
@@ -305,7 +305,7 @@
started_ = true;
total_iterations_ = skipped() ? 0 : max_iterations;
if (BENCHMARK_BUILTIN_EXPECT(profiler_manager_ != nullptr, false)) {
- profiler_manager_->AfterSetupStart();
+ profiler_manager_->AfterSetupStartWithState(*this);
}
manager_->StartStopBarrier();
if (!skipped()) {
@@ -323,7 +323,7 @@
finished_ = true;
manager_->StartStopBarrier();
if (BENCHMARK_BUILTIN_EXPECT(profiler_manager_ != nullptr, false)) {
- profiler_manager_->BeforeTeardownStop();
+ profiler_manager_->BeforeTeardownStopWithState(*this);
}
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index e9edd42..f33209c 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -217,6 +217,9 @@
compile_benchmark_test(profiler_manager_iterations_test)
benchmark_add_test(NAME profiler_manager_iterations COMMAND profiler_manager_iterations_test)
+compile_benchmark_test(profiler_manager_state_test)
+benchmark_add_test(NAME profiler_manager_state COMMAND profiler_manager_state_test)
+
compile_output_test(complexity_test)
benchmark_add_test(NAME complexity_benchmark COMMAND complexity_test --benchmark_min_time=1000000x)
diff --git a/test/profiler_manager_state_test.cc b/test/profiler_manager_state_test.cc
new file mode 100644
index 0000000..192600e
--- /dev/null
+++ b/test/profiler_manager_state_test.cc
@@ -0,0 +1,84 @@
+#include <cassert>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark_api.h"
+#include "benchmark/managers.h"
+#include "benchmark/registration.h"
+#include "benchmark/reporter.h"
+#include "benchmark/state.h"
+#include "benchmark/utils.h"
+
+namespace {
+
+class StateProfilerManager : public benchmark::ProfilerManager {
+ public:
+ void AfterSetupStartWithState(const benchmark::State& state) override {
+ ++start_called;
+ start_name = state.name();
+ }
+
+ void BeforeTeardownStopWithState(const benchmark::State& state) override {
+ ++stop_called;
+ stop_name = state.name();
+ }
+
+ int start_called = 0;
+ int stop_called = 0;
+ std::string start_name;
+ std::string stop_name;
+};
+
+class LegacyProfilerManager : public benchmark::ProfilerManager {
+ public:
+ void AfterSetupStart() override { ++start_called; }
+ void BeforeTeardownStop() override { ++stop_called; }
+
+ int start_called = 0;
+ int stop_called = 0;
+};
+
+class NullReporter : public benchmark::BenchmarkReporter {
+ public:
+ bool ReportContext(const Context& /*context*/) override { return true; }
+ void ReportRuns(const std::vector<Run>& /*report*/) override {}
+};
+
+void BM_Profiled(benchmark::State& state) {
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(state.iterations());
+ }
+}
+BENCHMARK(BM_Profiled);
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ benchmark::MaybeReenterWithoutASLR(argc, argv);
+ benchmark::Initialize(&argc, argv);
+
+ NullReporter null_reporter;
+
+ StateProfilerManager state_profiler;
+ benchmark::RegisterProfilerManager(&state_profiler);
+ size_t run_count =
+ benchmark::RunSpecifiedBenchmarks(&null_reporter, "BM_Profiled$");
+ benchmark::RegisterProfilerManager(nullptr);
+
+ assert(run_count == 1);
+ assert(state_profiler.start_called == 1);
+ assert(state_profiler.stop_called == 1);
+ assert(state_profiler.start_name == "BM_Profiled");
+ assert(state_profiler.stop_name == "BM_Profiled");
+
+ LegacyProfilerManager legacy_profiler;
+ benchmark::RegisterProfilerManager(&legacy_profiler);
+ run_count = benchmark::RunSpecifiedBenchmarks(&null_reporter, "BM_Profiled$");
+ benchmark::RegisterProfilerManager(nullptr);
+
+ assert(run_count == 1);
+ assert(legacy_profiler.start_called == 1);
+ assert(legacy_profiler.stop_called == 1);
+
+ return 0;
+}