2

I have searched around a bit and found many examples and discussions of cases where you would use std::bind instead of a lambda, but the burning question I have is whether or not there is any performance benefit to one over the other. I will describe my use case:

I have a generic A* I have implemented, to which I pass successor, heuristic distance, and move cost functions.

Here is an example of my heuristic function ready to be passed off for a search (in both forms):

std::function<float(const Location*, const Location*)> hdist = std::bind(&TerrainMap::straightLineDist, this, std::placeholders::_1, std::placeholders::_2);

std::function<float(const Location*, const Location*)> hdist2 = [this](const Location* a, const Location* b){
    return straightLineDist(a,b);
};

Is there any difference in the performance of these approaches? I realize the difference is probably negligible but I am curious enough to want to know.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
tbotz
  • 167
  • 2
  • 7
  • 9
    Profile to be sure. – HolyBlackCat Mar 13 '18 at 00:03
  • 1
    Alternatively look at the [assembler code](https://godbolt.org/g/uh8iQh). I can't read assembler properly, but I can see that the bind version has a lot more of it. – nwp Mar 13 '18 at 00:20
  • 3
    In both cases you should probably be using `auto`. The biggest advantage for the lambda (the compiler knows the exact type and can optimize more aggressively) is lost when you assign to an `std::function`. – Stephen Newell Mar 13 '18 at 00:29
  • This can't be answered without knowing the exact compiler brand and version, and yes, inspecting assembly and profiling are two generally useful tools for that. But also, if any `bind` expression does perform better than a directly equivalent lambda, that would be evidence of a missed opportunity for the compiler to optimize the lambda. – aschepler Mar 13 '18 at 01:07

1 Answers1

2

Is there any difference in the performance of these approaches?

Perhaps, perhaps not; as commenters suggest - profile to check, or look at the assemby code you get (e.g. using the GodBolt Compiler Explorer). But you're asking the wrong question, for two main reasons:

  1. You should probably not be passing lambda's, nor bind() results, around in the part of your code that's performance-critical.
  2. You should definitely avoid invoking arbitrary functions via function pointer or std::function variables in performance-critical areas of your code (except if this can be de-virtualized and inlined by the compiler).

and one mind reason:

  1. Lambdas (and std::bind()'s) are usable, and useful, without being wrapped in std::function; this wrapper has its own performance penalty, so you would only be comparing one way of using these constructs.

Bottom line recommendation: Just use Lambdas. They're cleaner, easier to understand, cheaper to compile, and more flexible syntactically. So don't worry and be happy :-) . And in performance-critical code, either use Lambda's without std::function, or don't use any of the two.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • Thanks for the insight. In my case I was passing function pointers to make my A* more generic `template QLinkedList astar(std::function(S)> getSuccessors, std::function gdist, std::function hdist, S start) {` – tbotz Mar 13 '18 at 01:07