mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-04 09:01:50 +01:00 
			
		
		
		
	Changes done to Nonius: * Moved things into "Catch::Benchmark" namespace * Benchmarks were integrated with `TEST_CASE`/`SECTION`/`GENERATE` macros * Removed Nonius's parameters for benchmarks, Generators should be used instead * Added relevant methods to the reporter interface (default-implemented, to avoid breaking existing 3rd party reporters) * Async processing is guarded with `_REENTRANT` macro for GCC/Clang, used by default on MSVC * Added a macro `CATCH_CONFIG_DISABLE_BENCHMARKING` that removes all traces of benchmarking from Catch
		
			
				
	
	
		
			106 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
    /*
 | 
						|
 *  Created by Joachim on 16/04/2019.
 | 
						|
 *  Adapted from donated nonius code.
 | 
						|
 *
 | 
						|
 *  Distributed under the Boost Software License, Version 1.0. (See accompanying
 | 
						|
 *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 | 
						|
 */
 | 
						|
 | 
						|
 // Dumb std::function implementation for consistent call overhead
 | 
						|
 | 
						|
#ifndef TWOBLUECUBES_CATCH_DETAIL_BENCHMARK_FUNCTION_HPP_INCLUDED
 | 
						|
#define TWOBLUECUBES_CATCH_DETAIL_BENCHMARK_FUNCTION_HPP_INCLUDED
 | 
						|
 | 
						|
#include "../catch_chronometer.hpp"
 | 
						|
#include "catch_complete_invoke.hpp"
 | 
						|
#include "../../catch_meta.hpp"
 | 
						|
 | 
						|
#include <cassert>
 | 
						|
#include <type_traits>
 | 
						|
#include <utility>
 | 
						|
#include <memory>
 | 
						|
 | 
						|
namespace Catch {
 | 
						|
    namespace Benchmark {
 | 
						|
        namespace Detail {
 | 
						|
            template <typename T>
 | 
						|
            using Decay = typename std::decay<T>::type;
 | 
						|
            template <typename T, typename U>
 | 
						|
            struct is_related
 | 
						|
                : std::is_same<Decay<T>, Decay<U>> {};
 | 
						|
 | 
						|
            /// We need to reinvent std::function because every piece of code that might add overhead
 | 
						|
            /// in a measurement context needs to have consistent performance characteristics so that we
 | 
						|
            /// can account for it in the measurement.
 | 
						|
            /// Implementations of std::function with optimizations that aren't always applicable, like
 | 
						|
            /// small buffer optimizations, are not uncommon.
 | 
						|
            /// This is effectively an implementation of std::function without any such optimizations;
 | 
						|
            /// it may be slow, but it is consistently slow.
 | 
						|
            struct BenchmarkFunction {
 | 
						|
            private:
 | 
						|
                struct callable {
 | 
						|
                    virtual void call(Chronometer meter) const = 0;
 | 
						|
                    virtual callable* clone() const = 0;
 | 
						|
                    virtual ~callable() = default;
 | 
						|
                };
 | 
						|
                template <typename Fun>
 | 
						|
                struct model : public callable {
 | 
						|
                    model(Fun&& fun) : fun(std::move(fun)) {}
 | 
						|
                    model(Fun const& fun) : fun(fun) {}
 | 
						|
 | 
						|
                    model<Fun>* clone() const override { return new model<Fun>(*this); }
 | 
						|
 | 
						|
                    void call(Chronometer meter) const override {
 | 
						|
                        call(meter, is_callable<Fun(Chronometer)>());
 | 
						|
                    }
 | 
						|
                    void call(Chronometer meter, std::true_type) const {
 | 
						|
                        fun(meter);
 | 
						|
                    }
 | 
						|
                    void call(Chronometer meter, std::false_type) const {
 | 
						|
                        meter.measure(fun);
 | 
						|
                    }
 | 
						|
 | 
						|
                    Fun fun;
 | 
						|
                };
 | 
						|
 | 
						|
                struct do_nothing { void operator()() const {} };
 | 
						|
 | 
						|
                template <typename T>
 | 
						|
                BenchmarkFunction(model<T>* c) : f(c) {}
 | 
						|
 | 
						|
            public:
 | 
						|
                BenchmarkFunction()
 | 
						|
                    : f(new model<do_nothing>{ {} }) {}
 | 
						|
 | 
						|
                template <typename Fun,
 | 
						|
                    typename std::enable_if<!is_related<Fun, BenchmarkFunction>::value, int>::type = 0>
 | 
						|
                    BenchmarkFunction(Fun&& fun)
 | 
						|
                    : f(new model<typename std::decay<Fun>::type>(std::forward<Fun>(fun))) {}
 | 
						|
 | 
						|
                BenchmarkFunction(BenchmarkFunction&& that)
 | 
						|
                    : f(std::move(that.f)) {}
 | 
						|
 | 
						|
                BenchmarkFunction(BenchmarkFunction const& that)
 | 
						|
                    : f(that.f->clone()) {}
 | 
						|
 | 
						|
                BenchmarkFunction& operator=(BenchmarkFunction&& that) {
 | 
						|
                    f = std::move(that.f);
 | 
						|
                    return *this;
 | 
						|
                }
 | 
						|
 | 
						|
                BenchmarkFunction& operator=(BenchmarkFunction const& that) {
 | 
						|
                    f.reset(that.f->clone());
 | 
						|
                    return *this;
 | 
						|
                }
 | 
						|
 | 
						|
                void operator()(Chronometer meter) const { f->call(meter); }
 | 
						|
 | 
						|
            private:
 | 
						|
                std::unique_ptr<callable> f;
 | 
						|
            };
 | 
						|
        } // namespace Detail
 | 
						|
    } // namespace Benchmark
 | 
						|
} // namespace Catch
 | 
						|
 | 
						|
#endif // TWOBLUECUBES_CATCH_DETAIL_BENCHMARK_FUNCTION_HPP_INCLUDED
 |