From 0fbf4f3e152e8fe9a41fa1a960ea3dac3cb76e59 Mon Sep 17 00:00:00 2001 From: Joe Burzinski Date: Mon, 18 Nov 2019 22:22:38 -0600 Subject: [PATCH] Fix wrong namespacing of benchmarking constructor helpers --- docs/benchmarks.md | 12 +-- src/catch2/benchmark/catch_constructor.hpp | 92 ++++++++++--------- tests/SelfTest/UsageTests/Benchmark.tests.cpp | 15 +++ 3 files changed, 67 insertions(+), 52 deletions(-) diff --git a/docs/benchmarks.md b/docs/benchmarks.md index 6513cc2d..ccc4175b 100644 --- a/docs/benchmarks.md +++ b/docs/benchmarks.md @@ -164,7 +164,7 @@ Note that it is not possible to simply use the same instance for different runs and resetting it between each run since that would pollute the measurements with the resetting code. -It is also possible to just provide an argument name to the simple `BENCHMARK` macro to get +It is also possible to just provide an argument name to the simple `BENCHMARK` macro to get the same semantics as providing a callable to `meter.measure` with `int` argument: ```c++ @@ -185,19 +185,17 @@ construct and destroy objects without dynamic allocation and in a way that lets you measure construction and destruction separately. ```c++ -BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter) -{ +BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter) { std::vector> storage(meter.runs()); meter.measure([&](int i) { storage[i].construct("thing"); }); -}) +}; -BENCHMARK_ADVANCED("destroy", [](Catch::Benchmark::Chronometer meter) -{ +BENCHMARK_ADVANCED("destroy")(Catch::Benchmark::Chronometer meter) { std::vector> storage(meter.runs()); for(auto&& o : storage) o.construct("thing"); meter.measure([&](int i) { storage[i].destruct(); }); -}) +}; ``` `Catch::Benchmark::storage_for` objects are just pieces of raw storage suitable for `T` diff --git a/src/catch2/benchmark/catch_constructor.hpp b/src/catch2/benchmark/catch_constructor.hpp index bf6dfec9..f12958f3 100644 --- a/src/catch2/benchmark/catch_constructor.hpp +++ b/src/catch2/benchmark/catch_constructor.hpp @@ -14,60 +14,62 @@ #include namespace Catch { - namespace Detail { - template - struct ObjectStorage - { - using TStorage = typename std::aligned_storage::value>::type; - - ObjectStorage() : data() {} - - ObjectStorage(const ObjectStorage& other) + namespace Benchmark { + namespace Detail { + template + struct ObjectStorage { - new(&data) T(other.stored_object()); - } + using TStorage = typename std::aligned_storage::value>::type; - ObjectStorage(ObjectStorage&& other) - { - new(&data) T(std::move(other.stored_object())); - } + ObjectStorage() : data() {} - ~ObjectStorage() { destruct_on_exit(); } + ObjectStorage(const ObjectStorage& other) + { + new(&data) T(other.stored_object()); + } - template - void construct(Args&&... args) - { - new (&data) T(std::forward(args)...); - } + ObjectStorage(ObjectStorage&& other) + { + new(&data) T(std::move(other.stored_object())); + } - template - typename std::enable_if::type destruct() - { - stored_object().~T(); - } + ~ObjectStorage() { destruct_on_exit(); } - private: - // If this is a constructor benchmark, destruct the underlying object - template - void destruct_on_exit(typename std::enable_if::type* = 0) { destruct(); } - // Otherwise, don't - template - void destruct_on_exit(typename std::enable_if::type* = 0) { } + template + void construct(Args&&... args) + { + new (&data) T(std::forward(args)...); + } - T& stored_object() - { - return *static_cast(static_cast(&data)); - } + template + typename std::enable_if::type destruct() + { + stored_object().~T(); + } - TStorage data; - }; - } + private: + // If this is a constructor benchmark, destruct the underlying object + template + void destruct_on_exit(typename std::enable_if::type* = 0) { destruct(); } + // Otherwise, don't + template + void destruct_on_exit(typename std::enable_if::type* = 0) { } - template - using storage_for = Detail::ObjectStorage; + T& stored_object() + { + return *static_cast(static_cast(&data)); + } - template - using destructable_object = Detail::ObjectStorage; -} + TStorage data; + }; + } // namespace Detail + + template + using storage_for = Detail::ObjectStorage; + + template + using destructable_object = Detail::ObjectStorage; + } // namespace Benchmark +} // namespace Catch #endif // TWOBLUECUBES_CATCH_CONSTRUCTOR_HPP_INCLUDED diff --git a/tests/SelfTest/UsageTests/Benchmark.tests.cpp b/tests/SelfTest/UsageTests/Benchmark.tests.cpp index fe2d736c..38ad6a9f 100644 --- a/tests/SelfTest/UsageTests/Benchmark.tests.cpp +++ b/tests/SelfTest/UsageTests/Benchmark.tests.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -127,4 +128,18 @@ TEST_CASE("Benchmark containers", "[!benchmark]") { REQUIRE(v[i] == generated); } } + + SECTION("construct and destroy example") { + BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter) { + std::vector> storage(meter.runs()); + meter.measure([&](int i) { storage[i].construct("thing"); }); + }; + + BENCHMARK_ADVANCED("destroy")(Catch::Benchmark::Chronometer meter) { + std::vector> storage(meter.runs()); + for(auto&& o : storage) + o.construct("thing"); + meter.measure([&](int i) { storage[i].destruct(); }); + }; + } }