Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/user_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -1066,6 +1066,29 @@ BENCHMARK(BM_SetInsert_With_Timer_Control)->Ranges({{1<<10, 8<<10}, {128, 512}})
```
<!-- {% 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
Expand Down
17 changes: 17 additions & 0 deletions include/benchmark/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,23 @@ inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::end() {
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)
Expand Down
3 changes: 3 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ benchmark_add_test(NAME complexity_benchmark COMMAND complexity_test --benchmark
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
###############################################################################
Expand Down
30 changes: 30 additions & 0 deletions test/scoped_pause_test.cc
Original file line number Diff line number Diff line change
@@ -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) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd strongly suggest to use ManualTime for this, not rely on the system timers doing the right thing.

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;
}
Loading