feat: Add ScopedPauseTiming RAII helper (#2157)
* feat: Add ScopedPauseTiming RAII helper
Adds a new `benchmark::ScopedPauseTiming` class that provides a convenient
RAII-style mechanism for pausing and resuming benchmark timers.
This is less error-prone than manually calling `PauseTiming` and
`ResumeTiming`, as it guarantees that the timer is resumed when the
scope is exited.
- Added `ScopedPauseTiming` to `include/benchmark/state.h`.
- Added a new test `test/scoped_pause_test.cc` to verify the
functionality and prevent regressions.
- Updated `test/CMakeLists.txt` to include the new test.
- Added documentation for the new feature in `docs/user_guide.md`.
* Bump astral-sh/setup-uv from 7.6.0 to 8.0.0 (#2160)
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 7.6.0 to 8.0.0.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/37802adc94f370d6bfd71619e3f0bf239e1f3b78...cec208311dfd045dd5311c1add060b2062131d57)
---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
dependency-version: 8.0.0
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Bump lukka/get-cmake from 4.3.0 to 4.3.1 (#2159)
Bumps [lukka/get-cmake](https://github.com/lukka/get-cmake) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/lukka/get-cmake/releases)
- [Changelog](https://github.com/lukka/get-cmake/blob/main/RELEASE_PROCESS.md)
- [Commits](https://github.com/lukka/get-cmake/compare/b78306120111dc2522750771cfd09ee7ca723687...ea83089aa35e08e459464341fe24ad024ee2466f)
---
updated-dependencies:
- dependency-name: lukka/get-cmake
dependency-version: 4.3.1
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dominic <510002+dmah42@users.noreply.github.com>
* Bump numpy from 2.4.3 to 2.4.4 in /tools (#2158)
Bumps [numpy](https://github.com/numpy/numpy) from 2.4.3 to 2.4.4.
- [Release notes](https://github.com/numpy/numpy/releases)
- [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst)
- [Commits](https://github.com/numpy/numpy/compare/v2.4.3...v2.4.4)
---
updated-dependencies:
- dependency-name: numpy
dependency-version: 2.4.4
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dominic <510002+dmah42@users.noreply.github.com>
* handle move operators
* Use manual time instead of real time for better repeatability
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
diff --git a/docs/user_guide.md b/docs/user_guide.md
index c09d775..1303196 100644
--- a/docs/user_guide.md
+++ b/docs/user_guide.md
@@ -1066,6 +1066,29 @@
```
<!-- {% endraw %} -->
+For convenience, a `ScopedPauseTiming` class is provided to manage pausing and
+resuming timers within a scope. This is less error-prone than manually calling
+`PauseTiming` and `ResumeTiming`.
+
+<!-- {% raw %} -->
+```c++
+static void BM_SetInsert_With_Scoped_Timer_Control(benchmark::State& state) {
+ std::set<int> data;
+ for (auto _ : state) {
+ {
+ benchmark::ScopedPauseTiming pause(state); // Pauses timing
+ data = ConstructRandomSet(state.range(0));
+ } // Timing resumes automatically when 'pause' goes out of scope
+
+ // The rest will be measured.
+ for (int j = 0; j < state.range(1); ++j)
+ data.insert(RandomNumber());
+ }
+}
+BENCHMARK(BM_SetInsert_With_Scoped_Timer_Control)->Ranges({{1<<10, 8<<10}, {128, 512}});
+```
+<!-- {% endraw %} -->
+
<a name="manual-timing" />
## Manual Timing
diff --git a/include/benchmark/state.h b/include/benchmark/state.h
index e9cdf05..356c550 100644
--- a/include/benchmark/state.h
+++ b/include/benchmark/state.h
@@ -256,6 +256,23 @@
return StateIterator();
}
+class ScopedPauseTiming {
+ public:
+ explicit ScopedPauseTiming(State& state) : state_(state) {
+ state_.PauseTiming();
+ }
+ ~ScopedPauseTiming() { state_.ResumeTiming(); }
+
+ ScopedPauseTiming(const ScopedPauseTiming&) = delete;
+ void operator=(const ScopedPauseTiming&) = delete;
+
+ ScopedPauseTiming(ScopedPauseTiming&&) = delete;
+ void operator=(ScopedPauseTiming&&) = delete;
+
+ private:
+ State& state_;
+};
+
} // namespace benchmark
#if defined(_MSC_VER)
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 2917efa..374c09f 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -225,6 +225,9 @@
compile_output_test(locale_impermeability_test)
benchmark_add_test(NAME locale_impermeability_test COMMAND locale_impermeability_test)
+compile_output_test(scoped_pause_test)
+benchmark_add_test(NAME scoped_pause_test COMMAND scoped_pause_test)
+
###############################################################################
# GoogleTest Unit Tests
###############################################################################
diff --git a/test/scoped_pause_test.cc b/test/scoped_pause_test.cc
new file mode 100644
index 0000000..93bcfc2
--- /dev/null
+++ b/test/scoped_pause_test.cc
@@ -0,0 +1,30 @@
+
+#include <chrono>
+#include <thread>
+
+#include "benchmark/benchmark.h"
+#include "output_test.h"
+
+// BM_ScopedPause sleeps for 10ms in a ScopedPauseTiming block.
+// The reported time should be much less than 10ms.
+void BM_ScopedPause(benchmark::State& state) {
+ for (auto _ : state) {
+ benchmark::ScopedPauseTiming pause(state);
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ state.SetIterationTime(0.0);
+ }
+}
+BENCHMARK(BM_ScopedPause)->UseManualTime()->Iterations(1);
+
+void CheckResults(Results const& results) {
+ // Check that the real time is much less than the 10ms sleep time.
+ // Allow for up to 1ms of timing noise/overhead.
+ CHECK_FLOAT_RESULT_VALUE(results, "real_time", LT, 1e6, 0.0);
+}
+CHECK_BENCHMARK_RESULTS("BM_ScopedPause", &CheckResults);
+
+int main(int argc, char* argv[]) {
+ benchmark::MaybeReenterWithoutASLR(argc, argv);
+ RunOutputTests(argc, argv);
+ return 0;
+}