Skip to content

Instantly share code, notes, and snippets.

@fadi-botros
Created September 25, 2021 16:04
Show Gist options
  • Save fadi-botros/401378c2f648d293a2eb1599e8e6e5be to your computer and use it in GitHub Desktop.
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
#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