// Copyright Catch2 Authors // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.txt or copy at // https://www.boost.org/LICENSE_1_0.txt) // SPDX-License-Identifier: BSL-1.0 // Adapted from donated nonius code. #include #include #include #include #include namespace { std::uint64_t Fibonacci(std::uint64_t number) { return number < 2 ? number : Fibonacci(number - 1) + Fibonacci(number - 2); } } TEST_CASE("Benchmark Fibonacci", "[!benchmark]") { CHECK(Fibonacci(0) == 0); // some more asserts.. CHECK(Fibonacci(5) == 5); // some more asserts.. REQUIRE( Fibonacci( 20 ) == 6'765 ); BENCHMARK( "Fibonacci 20" ) { return Fibonacci(20); }; REQUIRE( Fibonacci( 25 ) == 75'025 ); BENCHMARK( "Fibonacci 25" ) { return Fibonacci(25); }; BENCHMARK("Fibonacci 30") { return Fibonacci(30); }; BENCHMARK("Fibonacci 35") { return Fibonacci(35); }; } TEST_CASE("Benchmark containers", "[!benchmark]") { static const int size = 100; std::vector v; std::map m; SECTION("without generator") { BENCHMARK("Load up a vector") { v = std::vector(); for (int i = 0; i < size; ++i) v.push_back(i); }; REQUIRE(v.size() == size); // test optimizer control BENCHMARK("Add up a vector's content") { uint64_t add = 0; for (std::size_t i = 0; i < size; ++i) add += static_cast(v[i]); return add; }; BENCHMARK("Load up a map") { m = std::map(); for (int i = 0; i < size; ++i) m.insert({ i, i + 1 }); }; REQUIRE(m.size() == size); BENCHMARK("Reserved vector") { v = std::vector(); v.reserve(size); for (int i = 0; i < size; ++i) v.push_back(i); }; REQUIRE(v.size() == size); BENCHMARK("Resized vector") { v = std::vector(); v.resize(size); for (int i = 0; i < size; ++i) v[static_cast(i)] = i; }; REQUIRE(v.size() == size); int array[size]; BENCHMARK("A fixed size array that should require no allocations") { for (int i = 0; i < size; ++i) array[i] = i; }; int sum = 0; for (int i = 0; i < size; ++i) sum += array[i]; REQUIRE(sum > size); SECTION("XYZ") { BENCHMARK_ADVANCED("Load up vector with chronometer")(Catch::Benchmark::Chronometer meter) { std::vector k; meter.measure([&](int idx) { k = std::vector(); for (int i = 0; i < size; ++i) k.push_back(idx); }); REQUIRE(k.size() == size); }; int runs = 0; BENCHMARK("Fill vector indexed", benchmarkIndex) { v = std::vector(); v.resize(size); for (std::size_t i = 0; i < size; ++i) v[i] = benchmarkIndex; runs = benchmarkIndex; }; for (size_t i = 0; i < v.size(); ++i) { REQUIRE(v[i] == runs); } } } SECTION("with generator") { auto generated = GENERATE(range(0, 10)); BENCHMARK("Fill vector generated") { v = std::vector(); v.resize(size); for (std::size_t i = 0; i < size; ++i) v[i] = generated; }; for (size_t i = 0; i < v.size(); ++i) { REQUIRE(v[i] == generated); } } SECTION("construct and destroy example") { BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter) { std::vector> storage(static_cast(meter.runs())); meter.measure([&](int i) { storage[static_cast(i)].construct("thing"); }); }; BENCHMARK_ADVANCED("destroy")(Catch::Benchmark::Chronometer meter) { std::vector> storage(static_cast(meter.runs())); for(auto&& o : storage) o.construct("thing"); meter.measure([&](int i) { storage[static_cast(i)].destruct(); }); }; } } TEST_CASE("Skip benchmark macros", "[!benchmark]") { std::vector v; BENCHMARK("fill vector") { v.emplace_back(1); v.emplace_back(2); v.emplace_back(3); }; REQUIRE(v.size() == 0); std::size_t counter{0}; BENCHMARK_ADVANCED("construct vector")(Catch::Benchmark::Chronometer meter) { std::vector> storage(static_cast(meter.runs())); meter.measure([&](int i) { storage[static_cast(i)].construct("thing"); counter++; }); }; REQUIRE(counter == 0); }