Remove copyability from BenchmarkFunction

Technically we should be able to remove moveability as well, but
then we would need a larger surgery. This already improves the
compile times and binary sizes by a surprising amount.
This commit is contained in:
Martin Hořeňovský 2024-07-22 09:50:24 +02:00
parent 595bf9864e
commit 22e6490325
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
4 changed files with 12 additions and 25 deletions

View File

@ -45,12 +45,12 @@ namespace Catch {
: fun(CATCH_MOVE(func)), name(CATCH_MOVE(benchmarkName)) {} : fun(CATCH_MOVE(func)), name(CATCH_MOVE(benchmarkName)) {}
template <typename Clock> template <typename Clock>
ExecutionPlan prepare(const IConfig &cfg, Environment env) const { ExecutionPlan prepare(const IConfig &cfg, Environment env) {
auto min_time = env.clock_resolution.mean * Detail::minimum_ticks; auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime())); auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(run_time), 1, fun); auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(run_time), 1, fun);
int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed)); int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FDuration>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations }; return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), CATCH_MOVE(fun), std::chrono::duration_cast<FDuration>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
} }
template <typename Clock = default_clock> template <typename Clock = default_clock>

View File

@ -11,7 +11,13 @@
namespace Catch { namespace Catch {
namespace Benchmark { namespace Benchmark {
namespace Detail { namespace Detail {
struct do_nothing {
void operator()() const {}
};
BenchmarkFunction::callable::~callable() = default; BenchmarkFunction::callable::~callable() = default;
BenchmarkFunction::BenchmarkFunction():
f( new model<do_nothing>{ {} } ){}
} // namespace Detail } // namespace Detail
} // namespace Benchmark } // namespace Benchmark
} // namespace Catch } // namespace Catch

View File

@ -35,22 +35,17 @@ namespace Catch {
private: private:
struct callable { struct callable {
virtual void call(Chronometer meter) const = 0; virtual void call(Chronometer meter) const = 0;
virtual Catch::Detail::unique_ptr<callable> clone() const = 0;
virtual ~callable(); // = default; virtual ~callable(); // = default;
callable() = default; callable() = default;
callable(callable const&) = default; callable(callable&&) = default;
callable& operator=(callable const&) = default; callable& operator=(callable&&) = default;
}; };
template <typename Fun> template <typename Fun>
struct model : public callable { struct model : public callable {
model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {} model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {}
model(Fun const& fun_) : fun(fun_) {} model(Fun const& fun_) : fun(fun_) {}
Catch::Detail::unique_ptr<callable> clone() const override {
return Catch::Detail::make_unique<model<Fun>>( *this );
}
void call(Chronometer meter) const override { void call(Chronometer meter) const override {
call(meter, is_callable<Fun(Chronometer)>()); call(meter, is_callable<Fun(Chronometer)>());
} }
@ -64,14 +59,8 @@ namespace Catch {
Fun fun; Fun fun;
}; };
struct do_nothing { void operator()() const {} };
template <typename T>
BenchmarkFunction(model<T>* c) : f(c) {}
public: public:
BenchmarkFunction() BenchmarkFunction();
: f(new model<do_nothing>{ {} }) {}
template <typename Fun, template <typename Fun,
std::enable_if_t<!is_related<Fun, BenchmarkFunction>::value, int> = 0> std::enable_if_t<!is_related<Fun, BenchmarkFunction>::value, int> = 0>
@ -81,20 +70,12 @@ namespace Catch {
BenchmarkFunction( BenchmarkFunction&& that ) noexcept: BenchmarkFunction( BenchmarkFunction&& that ) noexcept:
f( CATCH_MOVE( that.f ) ) {} f( CATCH_MOVE( that.f ) ) {}
BenchmarkFunction(BenchmarkFunction const& that)
: f(that.f->clone()) {}
BenchmarkFunction& BenchmarkFunction&
operator=( BenchmarkFunction&& that ) noexcept { operator=( BenchmarkFunction&& that ) noexcept {
f = CATCH_MOVE( that.f ); f = CATCH_MOVE( that.f );
return *this; return *this;
} }
BenchmarkFunction& operator=(BenchmarkFunction const& that) {
f = that.f->clone();
return *this;
}
void operator()(Chronometer meter) const { f->call(meter); } void operator()(Chronometer meter) const { f->call(meter); }
private: private:

View File

@ -20,7 +20,7 @@ namespace Catch {
template <typename Clock, typename Fun, typename... Args> template <typename Clock, typename Fun, typename... Args>
TimingOf<Fun, Args...> measure(Fun&& fun, Args&&... args) { TimingOf<Fun, Args...> measure(Fun&& fun, Args&&... args) {
auto start = Clock::now(); auto start = Clock::now();
auto&& r = Detail::complete_invoke(fun, CATCH_FORWARD(args)...); auto&& r = Detail::complete_invoke(CATCH_FORWARD(fun), CATCH_FORWARD(args)...);
auto end = Clock::now(); auto end = Clock::now();
auto delta = end - start; auto delta = end - start;
return { delta, CATCH_FORWARD(r), 1 }; return { delta, CATCH_FORWARD(r), 1 };