line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
// Copyright Catch2 Authors |
3
|
|
|
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. |
4
|
|
|
|
|
|
|
// (See accompanying file LICENSE_1_0.txt or copy at |
5
|
|
|
|
|
|
|
// https://www.boost.org/LICENSE_1_0.txt) |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
// SPDX-License-Identifier: BSL-1.0 |
8
|
|
|
|
|
|
|
// Adapted from donated nonius code. |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
#ifndef CATCH_BENCHMARK_HPP_INCLUDED |
11
|
|
|
|
|
|
|
#define CATCH_BENCHMARK_HPP_INCLUDED |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
#include |
14
|
|
|
|
|
|
|
#include |
15
|
|
|
|
|
|
|
#include |
16
|
|
|
|
|
|
|
#include |
17
|
|
|
|
|
|
|
#include |
18
|
|
|
|
|
|
|
#include |
19
|
|
|
|
|
|
|
#include |
20
|
|
|
|
|
|
|
#include |
21
|
|
|
|
|
|
|
#include |
22
|
|
|
|
|
|
|
#include |
23
|
|
|
|
|
|
|
#include |
24
|
|
|
|
|
|
|
#include |
25
|
|
|
|
|
|
|
#include |
26
|
|
|
|
|
|
|
#include |
27
|
|
|
|
|
|
|
#include |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
#include |
30
|
|
|
|
|
|
|
#include |
31
|
|
|
|
|
|
|
#include |
32
|
|
|
|
|
|
|
#include |
33
|
|
|
|
|
|
|
#include |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
namespace Catch { |
36
|
|
|
|
|
|
|
namespace Benchmark { |
37
|
0
|
|
|
|
|
|
struct Benchmark { |
38
|
0
|
|
|
|
|
|
Benchmark(std::string&& benchmarkName) |
39
|
0
|
|
|
|
|
|
: name(CATCH_MOVE(benchmarkName)) {} |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
template |
42
|
|
|
|
|
|
|
Benchmark(std::string&& benchmarkName , FUN &&func) |
43
|
|
|
|
|
|
|
: fun(CATCH_MOVE(func)), name(CATCH_MOVE(benchmarkName)) {} |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
template |
46
|
0
|
|
|
|
|
|
ExecutionPlan> prepare(const IConfig &cfg, Environment> env) const { |
47
|
0
|
|
|
|
|
|
auto min_time = env.clock_resolution.mean * Detail::minimum_ticks; |
48
|
0
|
0
|
|
|
|
|
auto run_time = std::max(min_time, std::chrono::duration_cast(cfg.benchmarkWarmupTime())); |
49
|
0
|
0
|
|
|
|
|
auto&& test = Detail::run_for_at_least(std::chrono::duration_cast>(run_time), 1, fun); |
50
|
0
|
|
|
|
|
|
int new_iters = static_cast(std::ceil(min_time * test.iterations / test.elapsed)); |
51
|
0
|
0
|
|
|
|
|
return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations }; |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
template |
55
|
0
|
|
|
|
|
|
void run() { |
56
|
0
|
0
|
|
|
|
|
auto const* cfg = getCurrentContext().getConfig(); |
|
|
0
|
|
|
|
|
|
57
|
|
|
|
|
|
|
|
58
|
0
|
0
|
|
|
|
|
auto env = Detail::measure_environment(); |
59
|
|
|
|
|
|
|
|
60
|
0
|
0
|
|
|
|
|
getResultCapture().benchmarkPreparing(name); |
|
|
0
|
|
|
|
|
|
61
|
|
|
|
|
|
|
CATCH_TRY{ |
62
|
0
|
|
|
|
|
|
auto plan = user_code([&] { |
63
|
0
|
|
|
|
|
|
return prepare(*cfg, env); |
64
|
0
|
0
|
|
|
|
|
}); |
|
|
0
|
|
|
|
|
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
BenchmarkInfo info { |
67
|
|
|
|
|
|
|
name, |
68
|
|
|
|
|
|
|
plan.estimated_duration.count(), |
69
|
|
|
|
|
|
|
plan.iterations_per_sample, |
70
|
0
|
0
|
|
|
|
|
cfg->benchmarkSamples(), |
71
|
0
|
0
|
|
|
|
|
cfg->benchmarkResamples(), |
72
|
|
|
|
|
|
|
env.clock_resolution.mean.count(), |
73
|
|
|
|
|
|
|
env.clock_cost.mean.count() |
74
|
0
|
0
|
|
|
|
|
}; |
75
|
|
|
|
|
|
|
|
76
|
0
|
0
|
|
|
|
|
getResultCapture().benchmarkStarting(info); |
|
|
0
|
|
|
|
|
|
77
|
|
|
|
|
|
|
|
78
|
0
|
|
|
|
|
|
auto samples = user_code([&] { |
79
|
0
|
|
|
|
|
|
return plan.template run(*cfg, env); |
80
|
0
|
0
|
|
|
|
|
}); |
81
|
|
|
|
|
|
|
|
82
|
0
|
0
|
|
|
|
|
auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end()); |
83
|
0
|
0
|
|
|
|
|
BenchmarkStats> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance }; |
|
|
0
|
|
|
|
|
|
84
|
0
|
0
|
|
|
|
|
getResultCapture().benchmarkEnded(stats); |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
85
|
|
|
|
|
|
|
} CATCH_CATCH_ANON (TestFailureException) { |
86
|
|
|
|
|
|
|
getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr); |
87
|
|
|
|
|
|
|
} CATCH_CATCH_ALL{ |
88
|
|
|
|
|
|
|
getResultCapture().benchmarkFailed(translateActiveException()); |
89
|
|
|
|
|
|
|
// We let the exception go further up so that the |
90
|
|
|
|
|
|
|
// test case is marked as failed. |
91
|
|
|
|
|
|
|
std::rethrow_exception(std::current_exception()); |
92
|
|
|
|
|
|
|
} |
93
|
0
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
// sets lambda to be used in fun *and* executes benchmark! |
96
|
|
|
|
|
|
|
template ::value, int> = 0> |
97
|
0
|
|
|
|
|
|
Benchmark & operator=(Fun func) { |
98
|
0
|
|
|
|
|
|
fun = Detail::BenchmarkFunction(func); |
99
|
0
|
|
|
|
|
|
run(); |
100
|
0
|
|
|
|
|
|
return *this; |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
0
|
|
|
|
|
|
explicit operator bool() { |
104
|
0
|
|
|
|
|
|
return true; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
private: |
108
|
|
|
|
|
|
|
Detail::BenchmarkFunction fun; |
109
|
|
|
|
|
|
|
std::string name; |
110
|
|
|
|
|
|
|
}; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
} // namespace Catch |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
#define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1 |
115
|
|
|
|
|
|
|
#define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2 |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
#define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\ |
118
|
|
|
|
|
|
|
if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ |
119
|
|
|
|
|
|
|
BenchmarkName = [&](int benchmarkIndex) |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
#define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\ |
122
|
|
|
|
|
|
|
if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ |
123
|
|
|
|
|
|
|
BenchmarkName = [&] |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
#if defined(CATCH_CONFIG_PREFIX_ALL) |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
#define CATCH_BENCHMARK(...) \ |
128
|
|
|
|
|
|
|
INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) |
129
|
|
|
|
|
|
|
#define CATCH_BENCHMARK_ADVANCED(name) \ |
130
|
|
|
|
|
|
|
INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name) |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
#else |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
#define BENCHMARK(...) \ |
135
|
|
|
|
|
|
|
INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) |
136
|
|
|
|
|
|
|
#define BENCHMARK_ADVANCED(name) \ |
137
|
|
|
|
|
|
|
INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name) |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
#endif |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
#endif // CATCH_BENCHMARK_HPP_INCLUDED |