Remix.run Logo
mgaunard 11 hours ago

I feel the results say more about the testing methodology and inlining settings than anything else.

Practically speaking all lambda options except for the one involving allocation (why would you even do that) are equivalent modulo inlining.

In particular, the caveat with the type erasure/helper variants is precisely that it prevents inlining, but given everything is in the same translation unit and isn't runtime-driven, it's still possible for the compiler to devirtualize.

I think it would be more interesting to make measurements when controlling explicitly whether inlining happens or the function type can be deduced statically.

gpderetta 10 hours ago | parent [-]

Given a Sufficiently Good™ compiler, yes, after devirtualization and heap elision all variants should generate exactly the same code. In practice is more complicated. Devirtualization needs to runs after (potentially interprocedural) constant propagation, which might be too late to take advantage of other optimization opportunities, unless the compiler keeps rerunning the optimization pipeline.

In a simple test I see that GCC14 has no problems completely removing the overhead of std::function_ref, but plain std::function is a huge mess.

Eventually we will get there [1], but in the meantime I prefer not to rely on devirtualization, and heap elision is more of a party trick.

edit: to compare early vs late inlining: while gcc 14 can remove one layer of function_ref, it seems that it cannot remove two layers, as apparently doesn't rerun the required passes to take advantage of the new opportunity. It has no problem of course removing an arbitrary large (but finite) layers of plain lambdas.

edit2: GCC15 can remove trivial uses of std::function, but this is very fragile. It still can't remove two function_ref.

[1] for example 25 years ago compilers were terrible at removing abstraction overhead of the STL, today there is very little cost.

mgaunard 3 hours ago | parent [-]

You can just write the benchmark in such a way that the optimizations are not possible.