Created
September 25, 2021 16:04
-
-
Save fadi-botros/401378c2f648d293a2eb1599e8e6e5be to your computer and use it in GitHub Desktop.
Quick-Benchmarking C++ unique_ptr vs callbacks when trying to use interfaces and dependency injection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <memory> | |
template<typename Parameter> | |
class Consumer { | |
public: | |
virtual void call(const Parameter &obj) const = 0; | |
virtual ~Consumer() {} | |
}; | |
template<typename Callable, typename Parameter> | |
class CallableWrapper: public Consumer<Parameter> { | |
private: | |
Callable callable; | |
public: | |
CallableWrapper(Callable callable): callable(callable) {} | |
virtual void call(const Parameter &obj) const override { | |
callable(obj); | |
} | |
virtual ~CallableWrapper() {} | |
}; | |
template<typename Parameter> | |
struct WrapHelper { | |
template<typename Callable> | |
static auto wrap(Callable callable) { | |
return CallableWrapper<Callable, Parameter>(callable); | |
} | |
}; | |
class Interface { | |
public: | |
virtual int method() const = 0; | |
virtual ~Interface() {} | |
}; | |
class InterfaceImpl: public Interface { | |
public: | |
virtual int method() const { return 0; } | |
virtual ~InterfaceImpl() {} | |
}; | |
std::unique_ptr<Interface> getAnImpl() { | |
return std::make_unique<InterfaceImpl>(); | |
} | |
void injectAnImplViaCallable(const Consumer<Interface> &consumer) { | |
// TO PREVENT INLINING | |
// DON'T USE IN PRODUCTION | |
auto ptr = alloca(4); | |
benchmark::DoNotOptimize(ptr); | |
// /////////////////////// | |
return consumer.call(InterfaceImpl()); | |
} | |
static void ViaReturnAndUniquePtr(benchmark::State& state) { | |
// Code inside this loop is measured repeatedly | |
for (auto _ : state) { | |
auto ptr = getAnImpl(); | |
int value = ptr->method(); | |
// Make sure the variable is not optimized away by compiler | |
benchmark::DoNotOptimize(value); | |
} | |
} | |
// Register the function as a benchmark | |
BENCHMARK(ViaReturnAndUniquePtr); | |
static void ViaCallbacks(benchmark::State& state) { | |
for (auto _ : state) { | |
int value; | |
injectAnImplViaCallable(WrapHelper<Interface>::wrap([&](const auto &obj){ | |
value = obj.method(); | |
})); | |
// Make sure the variable is not optimized away by compiler | |
benchmark::DoNotOptimize(value); | |
} | |
} | |
BENCHMARK(ViaCallbacks); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment