mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-25 23:06:10 +01:00
Reduce compilation costs of benchmarks
We replaced some simple std::algorithm usage by loops, and reduced header inclusion.
This commit is contained in:
parent
7d07efc92b
commit
fe64c28925
@ -17,8 +17,7 @@
|
|||||||
#include <catch2/benchmark/detail/catch_repeat.hpp>
|
#include <catch2/benchmark/detail/catch_repeat.hpp>
|
||||||
#include <catch2/benchmark/detail/catch_run_for_at_least.hpp>
|
#include <catch2/benchmark/detail/catch_run_for_at_least.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <vector>
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Benchmark {
|
namespace Benchmark {
|
||||||
@ -41,14 +40,17 @@ namespace Catch {
|
|||||||
Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_iterations, Detail::repeat(now<Clock>{}));
|
Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_iterations, Detail::repeat(now<Clock>{}));
|
||||||
|
|
||||||
std::vector<FloatDuration<Clock>> times;
|
std::vector<FloatDuration<Clock>> times;
|
||||||
times.reserve(cfg.benchmarkSamples());
|
const auto num_samples = cfg.benchmarkSamples();
|
||||||
std::generate_n(std::back_inserter(times), cfg.benchmarkSamples(), [this, env] {
|
times.reserve( num_samples );
|
||||||
|
for ( size_t i = 0; i < num_samples; ++i ) {
|
||||||
Detail::ChronometerModel<Clock> model;
|
Detail::ChronometerModel<Clock> model;
|
||||||
this->benchmark( Chronometer( model, iterations_per_sample ) );
|
this->benchmark( Chronometer( model, iterations_per_sample ) );
|
||||||
auto sample_time = model.elapsed() - env.clock_cost.mean;
|
auto sample_time = model.elapsed() - env.clock_cost.mean;
|
||||||
if (sample_time < FloatDuration<Clock>::zero()) sample_time = FloatDuration<Clock>::zero();
|
if ( sample_time < FloatDuration<Clock>::zero() ) {
|
||||||
return sample_time / iterations_per_sample;
|
sample_time = FloatDuration<Clock>::zero();
|
||||||
});
|
}
|
||||||
|
times.push_back(sample_time / iterations_per_sample);
|
||||||
|
}
|
||||||
return times;
|
return times;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -10,14 +10,11 @@
|
|||||||
#ifndef CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
|
#ifndef CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
|
||||||
#define CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
|
#define CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
|
||||||
|
|
||||||
#include <catch2/benchmark/catch_clock.hpp>
|
|
||||||
#include <catch2/benchmark/catch_estimate.hpp>
|
#include <catch2/benchmark/catch_estimate.hpp>
|
||||||
#include <catch2/benchmark/catch_outlier_classification.hpp>
|
#include <catch2/benchmark/catch_outlier_classification.hpp>
|
||||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Benchmark {
|
namespace Benchmark {
|
||||||
@ -33,7 +30,9 @@ namespace Catch {
|
|||||||
operator SampleAnalysis<Duration2>() const {
|
operator SampleAnalysis<Duration2>() const {
|
||||||
std::vector<Duration2> samples2;
|
std::vector<Duration2> samples2;
|
||||||
samples2.reserve(samples.size());
|
samples2.reserve(samples.size());
|
||||||
std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); });
|
for (auto const& d : samples) {
|
||||||
|
samples2.push_back(Duration2(d));
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
CATCH_MOVE(samples2),
|
CATCH_MOVE(samples2),
|
||||||
mean,
|
mean,
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
#include <catch2/interfaces/catch_interfaces_config.hpp>
|
#include <catch2/interfaces/catch_interfaces_config.hpp>
|
||||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iterator>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
@ -28,7 +26,9 @@ namespace Catch {
|
|||||||
if (!cfg.benchmarkNoAnalysis()) {
|
if (!cfg.benchmarkNoAnalysis()) {
|
||||||
std::vector<double> samples;
|
std::vector<double> samples;
|
||||||
samples.reserve(static_cast<size_t>(last - first));
|
samples.reserve(static_cast<size_t>(last - first));
|
||||||
std::transform(first, last, std::back_inserter(samples), [](Duration d) { return d.count(); });
|
for (auto current = first; current != last; ++current) {
|
||||||
|
samples.push_back( current->count() );
|
||||||
|
}
|
||||||
|
|
||||||
auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), samples.begin(), samples.end());
|
auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), samples.begin(), samples.end());
|
||||||
auto outliers = Catch::Benchmark::Detail::classify_outliers(samples.begin(), samples.end());
|
auto outliers = Catch::Benchmark::Detail::classify_outliers(samples.begin(), samples.end());
|
||||||
@ -43,7 +43,10 @@ namespace Catch {
|
|||||||
};
|
};
|
||||||
std::vector<Duration> samples2;
|
std::vector<Duration> samples2;
|
||||||
samples2.reserve(samples.size());
|
samples2.reserve(samples.size());
|
||||||
std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](double d) { return Duration(d); });
|
for (auto s : samples) {
|
||||||
|
samples2.push_back( Duration( s ) );
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
CATCH_MOVE(samples2),
|
CATCH_MOVE(samples2),
|
||||||
wrap_estimate(analysis.mean),
|
wrap_estimate(analysis.mean),
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include <catch2/internal/catch_unique_ptr.hpp>
|
#include <catch2/internal/catch_unique_ptr.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
@ -30,13 +29,16 @@ namespace Catch {
|
|||||||
std::vector<double> resolution(int k) {
|
std::vector<double> resolution(int k) {
|
||||||
std::vector<TimePoint<Clock>> times;
|
std::vector<TimePoint<Clock>> times;
|
||||||
times.reserve(static_cast<size_t>(k + 1));
|
times.reserve(static_cast<size_t>(k + 1));
|
||||||
std::generate_n(std::back_inserter(times), k + 1, now<Clock>{});
|
for ( int i = 0; i < k + 1; ++i ) {
|
||||||
|
times.push_back( Clock::now() );
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<double> deltas;
|
std::vector<double> deltas;
|
||||||
deltas.reserve(static_cast<size_t>(k));
|
deltas.reserve(static_cast<size_t>(k));
|
||||||
std::transform(std::next(times.begin()), times.end(), times.begin(),
|
for ( size_t idx = 1; idx < times.size(); ++idx ) {
|
||||||
std::back_inserter(deltas),
|
deltas.push_back( static_cast<double>(
|
||||||
[](TimePoint<Clock> a, TimePoint<Clock> b) { return static_cast<double>((a - b).count()); });
|
( times[idx] - times[idx - 1] ).count() ) );
|
||||||
|
}
|
||||||
|
|
||||||
return deltas;
|
return deltas;
|
||||||
}
|
}
|
||||||
@ -84,9 +86,11 @@ namespace Catch {
|
|||||||
std::vector<double> times;
|
std::vector<double> times;
|
||||||
int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));
|
int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));
|
||||||
times.reserve(static_cast<size_t>(nsamples));
|
times.reserve(static_cast<size_t>(nsamples));
|
||||||
std::generate_n(std::back_inserter(times), nsamples, [time_clock, &r] {
|
for ( int s = 0; s < nsamples; ++s ) {
|
||||||
return static_cast<double>((time_clock(r.iterations) / r.iterations).count());
|
times.push_back( static_cast<double>(
|
||||||
});
|
( time_clock( r.iterations ) / r.iterations )
|
||||||
|
.count() ) );
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
FloatDuration<Clock>(mean(times.begin(), times.end())),
|
FloatDuration<Clock>(mean(times.begin(), times.end())),
|
||||||
classify_outliers(times.begin(), times.end()),
|
classify_outliers(times.begin(), times.end()),
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <iterator>
|
#include <numeric>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
|
|
||||||
@ -35,12 +35,19 @@ using Catch::Benchmark::Detail::sample;
|
|||||||
|
|
||||||
sample out;
|
sample out;
|
||||||
out.reserve(resamples);
|
out.reserve(resamples);
|
||||||
std::generate_n(std::back_inserter(out), resamples, [n, first, &estimator, &dist, &rng] {
|
// We allocate the vector outside the loop to avoid realloc per resample
|
||||||
std::vector<double> resampled;
|
std::vector<double> resampled;
|
||||||
resampled.reserve( n );
|
resampled.reserve( n );
|
||||||
std::generate_n(std::back_inserter(resampled), n, [first, &dist, &rng] { return first[static_cast<std::ptrdiff_t>(dist(rng))]; });
|
for ( size_t i = 0; i < resamples; ++i ) {
|
||||||
return estimator(resampled.begin(), resampled.end());
|
resampled.clear();
|
||||||
});
|
for ( size_t s = 0; s < n; ++s ) {
|
||||||
|
resampled.push_back(
|
||||||
|
first[static_cast<std::ptrdiff_t>( dist( rng ) )] );
|
||||||
|
}
|
||||||
|
const auto estimate =
|
||||||
|
estimator( resampled.begin(), resampled.end() );
|
||||||
|
out.push_back( estimate );
|
||||||
|
}
|
||||||
std::sort(out.begin(), out.end());
|
std::sort(out.begin(), out.end());
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <numeric>
|
|
||||||
#include <tuple>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
@ -77,13 +75,13 @@ namespace Catch {
|
|||||||
|
|
||||||
sample jack = jackknife(estimator, first, last);
|
sample jack = jackknife(estimator, first, last);
|
||||||
double jack_mean = mean(jack.begin(), jack.end());
|
double jack_mean = mean(jack.begin(), jack.end());
|
||||||
double sum_squares, sum_cubes;
|
double sum_squares = 0, sum_cubes = 0;
|
||||||
std::tie(sum_squares, sum_cubes) = std::accumulate(jack.begin(), jack.end(), std::make_pair(0., 0.), [jack_mean](std::pair<double, double> sqcb, double x) -> std::pair<double, double> {
|
for (double x : jack) {
|
||||||
auto d = jack_mean - x;
|
auto difference = jack_mean - x;
|
||||||
auto d2 = d * d;
|
auto square = difference * difference;
|
||||||
auto d3 = d2 * d;
|
auto cube = square * difference;
|
||||||
return { sqcb.first + d2, sqcb.second + d3 };
|
sum_squares += square; sum_cubes += cube;
|
||||||
});
|
}
|
||||||
|
|
||||||
double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5));
|
double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5));
|
||||||
long n = static_cast<long>(resample.size());
|
long n = static_cast<long>(resample.size());
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include <catch2/benchmark/detail/catch_benchmark_function.hpp>
|
#include <catch2/benchmark/detail/catch_benchmark_function.hpp>
|
||||||
#include <catch2/benchmark/detail/catch_estimate_clock.hpp>
|
#include <catch2/benchmark/detail/catch_estimate_clock.hpp>
|
||||||
|
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct manual_clock {
|
struct manual_clock {
|
||||||
public:
|
public:
|
||||||
|
Loading…
Reference in New Issue
Block a user