Woid is an extremely customizable high-performance type-erasure header-only library. It provides containers like std::any, std::function and tools for non-intrusive polymorphism.
Key features:
- Performance
- Value semantics
- Move-only type support
- Duck typing
- Extreme customizability
In my current benchmarks it outperforms std::any, std::function, inheritance-based polymorphism and some well-known libraries like function2, boost::te and microsoft/proxy.
I want to make sure the comparison is fair, therefore, your advice on how to better tune the existing libraries is rather welcome.
struct Square {
double side;
double area() const { return side * side; }
};
struct Shape : woid::InterfaceBuilder
::Fun<"area", [](const auto& obj) -> double { return obj.area(); } >
::Build {
auto area() const { return call<"area">(); }
};
auto a = Shape{Square{1.5}}.area();
And of course I'm here to answer your questions.In my experience the typical implementations of std::function are slow-ish during construction/copying but calling an existing object is okay.
Have you compared just the performance of calling type erased functions? Is there still a difference due to cache locality?
Here I wrap std::less<int> into different wrappers (and of them manage to do SBO) and feed it into std::sort. Unless std::sort does a ton of copies, this is predominantly down to function invocation, not instantiation/lifetime management.
There Woid is up to about 60% faster than std::function if it leverages the triviality of std::less<int>. The advantage goes to 30% if don't optimize for trivial types. And either of the wrappers considered are much slower than just using the lambda directly (see the Id "wrapper") as the type-erased wrappers inhibit inlining.
I also do the same bench, but with a "big" less<int>, so that std::function fails the SBO, there the gains go up to 2-2.5x. https://github.com/akopich/woid/blob/main/bench/plots/FunBen...