Skip to content
File

Blob: src/workerd/tests/bench-tools.h

cpp58 lines
1// Copyright (c) 2023 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4 
5#pragma once
6// Used to provide support tools for benchmarking. Many use cases will already be covered by the
7// microbenchmark API.
8 
9#include <benchmark/benchmark.h>
10 
11#include <kj/test.h>
12 
13// Configure tcmalloc for deterministic benchmarks on Linux.
14// tcmalloc uses probabilistic heap sampling which can introduce variance in benchmark results.
15// WD_USE_TCMALLOC is defined when tcmalloc is enabled (Linux + use_tcmalloc flag).
16#ifdef WD_USE_TCMALLOC
17#include "tcmalloc/malloc_extension.h"
18 
19namespace workerd::bench {
20 
21struct TcmallocBenchmarkConfig {
22 TcmallocBenchmarkConfig() {
23 // Disable heap profiling sampling by setting interval to max value.
24 // Default is ~512KB which causes probabilistic sampling of allocations.
25 tcmalloc::MallocExtension::SetProfileSamplingInterval(std::numeric_limits<int64_t>::max());
26 
27 // Disable GWP-ASan guarded sampling. A negative value disables it.
28 tcmalloc::MallocExtension::SetGuardedSamplingInterval(-1);
29 
30 // Disable background memory release actions that can cause timing variance.
31 tcmalloc::MallocExtension::SetBackgroundProcessActionsEnabled(false);
32 }
33};
34 
35// Global instance ensures configuration runs before main().
36inline TcmallocBenchmarkConfig tcmallocBenchmarkConfig;
37 
38} // namespace workerd::bench
39#endif // defined(WD_USE_TCMALLOC)
40 
41// Define a benchmark. Use microseconds instead of nanoseconds by default, most tests run long
42// enough to not need ns precision.
43#define WD_BENCHMARK(X) BENCHMARK(X)->Unit(benchmark::kMicrosecond)
44 
45// Macro inspired by KJ_TEST() to enable benchmarking without requiring the benchmark::State
46// argument and make it easy to convert tests to benchmarks. Make sure the linker fails if tests are
47// not in anonymous namespaces.
48#define WD_BENCH(description) \
49 extern int KJ_CONCAT(YouMustWrapTestsInAnonymousNamespace, __COUNTER__) KJ_UNUSED; \
50 void KJ_UNIQUE_NAME(Bench)(); \
51 void KJ_UNIQUE_NAME(BenchImpl)(benchmark::State & state) { \
52 for (auto _: state) { \
53 KJ_UNIQUE_NAME(Bench)(); \
54 } \
55 } \
56 WD_BENCHMARK(KJ_UNIQUE_NAME(BenchImpl))->Name(description); \
57 void KJ_UNIQUE_NAME(Bench)()