Skip to content

Commit 4dd226e

Browse files
committed
ref: exclude benchmark harness from measurement via collection steady-state
Toggle callgrind collection off once at process start and make the PauseTiming()/ResumeTiming() toggles unconditional. Collection is now only enabled inside the benchmark loop, so State setup, timer reads and instrument-hooks zero/dump requests no longer appear in the measurement, and the codspeed_in_benchmark_loop_ gating flag is no longer needed. The toggle is inlined via CALLGRIND_TOGGLE_COLLECT directly (instead of calling the instrument-hooks wrapper) so no toggle frame shows up in flamegraphs; the counted boundary shrinks to the ResumeTiming() epilogue (~6 instructions). SkipWithMessage/SkipWithError restore the toggle parity when a benchmark is skipped mid-loop without pausing. Refs COD-2033
1 parent 198b668 commit 4dd226e

2 files changed

Lines changed: 24 additions & 37 deletions

File tree

google_benchmark/include/benchmark/benchmark.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -949,15 +949,6 @@ class BENCHMARK_EXPORT BENCHMARK_INTERNAL_CACHELINE_ALIGNED State {
949949
#if defined(CODSPEED_ANALYSIS) || defined(CODSPEED_WALLTIME)
950950
codspeed::CodSpeed* codspeed_;
951951
#endif
952-
#ifdef CODSPEED_ANALYSIS
953-
// True between the implicit ResumeTiming() in StartKeepRunning() and the
954-
// implicit PauseTiming() in FinishKeepRunning(). Only explicit user
955-
// PauseTiming()/ResumeTiming() calls (inside the benchmark loop) may
956-
// toggle callgrind collection: CALLGRIND_TOGGLE_COLLECT is parity-based,
957-
// and collection starts enabled, so the implicit bracket calls must not
958-
// toggle or they would invert the collection state for the whole run.
959-
bool codspeed_in_benchmark_loop_;
960-
#endif
961952
#ifdef CODSPEED_WALLTIME
962953
uint64_t resume_timestamp_;
963954
#endif

google_benchmark/src/benchmark.cc

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,24 @@
6161
#include "thread_timer.h"
6262

6363
namespace benchmark {
64+
65+
#ifdef CODSPEED_ANALYSIS
66+
// Callgrind cost collection is kept off outside the benchmark loop (one
67+
// initial toggle below, inverting the --collect-atstart=yes default) and
68+
// toggled on/off by ResumeTiming()/PauseTiming(). This keeps harness code and
69+
// paused sections out of the measurement without flushing the simulated cache
70+
// (unlike CALLGRIND_STOP_INSTRUMENTATION). The toggle must be the first
71+
// statement in PauseTiming() and the last in ResumeTiming().
72+
#define CODSPEED_TOGGLE_COLLECT() CALLGRIND_TOGGLE_COLLECT
73+
namespace {
74+
struct CodSpeedCollectInit {
75+
CodSpeedCollectInit() { CODSPEED_TOGGLE_COLLECT(); }
76+
} const codspeed_collect_init;
77+
} // namespace
78+
#else
79+
#define CODSPEED_TOGGLE_COLLECT()
80+
#endif
81+
6482
// Print a list of benchmarks. This option overrides all other options.
6583
BM_DEFINE_bool(benchmark_list_tests, false);
6684

@@ -199,9 +217,6 @@ State::State(std::string name, IterationCount max_iters,
199217
#if defined(CODSPEED_ANALYSIS) || defined(CODSPEED_WALLTIME)
200218
codspeed_(codspeed),
201219
#endif
202-
#ifdef CODSPEED_ANALYSIS
203-
codspeed_in_benchmark_loop_(false),
204-
#endif
205220
#ifdef CODSPEED_WALLTIME
206221
resume_timestamp_(0),
207222
#endif
@@ -275,15 +290,7 @@ void State::PauseTiming() {
275290
#ifdef CODSPEED_WALLTIME
276291
uint64_t pause_timestamp = measurement_current_timestamp();
277292
#endif
278-
#ifdef CODSPEED_ANALYSIS
279-
// Suspend callgrind cost collection for the paused section. Toggling
280-
// collection (unlike stopping instrumentation) does not flush the
281-
// simulated cache, so it adds no artificial cold-cache cost to the
282-
// measured region.
283-
if (codspeed_in_benchmark_loop_) {
284-
callgrind_toggle_collect();
285-
}
286-
#endif
293+
CODSPEED_TOGGLE_COLLECT();
287294

288295
// Add in time accumulated so far
289296
BM_CHECK(started_ && !finished_ && !skipped());
@@ -322,12 +329,7 @@ void State::ResumeTiming() {
322329
BM_CHECK(resume_timestamp_ == 0);
323330
resume_timestamp_ = measurement_current_timestamp();
324331
#endif
325-
#ifdef CODSPEED_ANALYSIS
326-
// Re-enable callgrind cost collection after a paused section.
327-
if (codspeed_in_benchmark_loop_) {
328-
callgrind_toggle_collect();
329-
}
330-
#endif
332+
CODSPEED_TOGGLE_COLLECT();
331333
}
332334

333335
void State::SkipWithMessage(const std::string& msg) {
@@ -342,6 +344,8 @@ void State::SkipWithMessage(const std::string& msg) {
342344
total_iterations_ = 0;
343345
if (timer_->running()) {
344346
timer_->StopTimer();
347+
// Skipped mid-loop without pausing: restore the collection-off state.
348+
CODSPEED_TOGGLE_COLLECT();
345349
}
346350
}
347351

@@ -357,6 +361,8 @@ void State::SkipWithError(const std::string& msg) {
357361
total_iterations_ = 0;
358362
if (timer_->running()) {
359363
timer_->StopTimer();
364+
// Skipped mid-loop without pausing: restore the collection-off state.
365+
CODSPEED_TOGGLE_COLLECT();
360366
}
361367
}
362368

@@ -379,22 +385,12 @@ void State::StartKeepRunning() {
379385
manager_->StartStopBarrier();
380386
if (!skipped()) {
381387
ResumeTiming();
382-
#ifdef CODSPEED_ANALYSIS
383-
// Arm collection toggling only after the implicit ResumeTiming() above,
384-
// so that only explicit user pauses inside the loop toggle collection.
385-
codspeed_in_benchmark_loop_ = true;
386-
#endif
387388
}
388389
}
389390

390391
void State::FinishKeepRunning() {
391392
BM_CHECK(started_ && (!finished_ || skipped()));
392393
if (!skipped()) {
393-
#ifdef CODSPEED_ANALYSIS
394-
// Disarm before the implicit PauseTiming() below so it does not toggle
395-
// collection off for the rest of the process.
396-
codspeed_in_benchmark_loop_ = false;
397-
#endif
398394
PauseTiming();
399395
}
400396
// Total iterations has now wrapped around past 0. Fix this.

0 commit comments

Comments
 (0)