c++lambda

Is there a performance difference by wrapping the code in an immediately invoked lambda expression?


Here is some code:

void f() 
{
    // stuff
    {
        // code
    }
}

It is also possible to write it in a strange way like this using lambdas instead of braces:

void f() 
{
    // same stuff as above
    [&]{
        // same code as above
    }();
}

Will there be any performance difference between the two versions?

According to my checks, there is no difference in generated assembly in clang when compiled with optimizations, so I assume there will be no performance overhead. But is this always the case?


Solution

  • Performance is hard to measure. Yet in this case it's still reasonable to reason about it.

    Every lambda is actually its own class with operator() implemented. This class has the same characteristics as one written in an unnamed namespace. Some relevant elements: its visibility is limited to the .cpp file and linked to it, it doesn't need to expose function pointers in the .obj file.

    What could a compiler do differently with an immediately invoked lambda? Not much actually: it can prevent inlining it. In my experience this has the same behavior as unnamed functions: either the function is too large or it's used multiple times. This last could be the result of a function returning a lambda.

    If the function is too large, then it could be that some paths where the function isn't called are faster by not inlining it. If it's called multiple times, it enlarges your binary to inline it twice, which could slow it down.

    To me, the bigger risk is that you call some templated function like std::sort with a lambda and copy that function body all over the place to bloat your binary. However as these were already templates before and std:: function is known for its measurable performance effects, I don't think it's worth the effort.

    That said, I use lambdas all over the place. I even provide class templates that have them as members in performance critical code. Lambdas are considered zero overhead, though depending on how you use them you could find edge cases where a flow in your program slows down.

    Some last piece of advice, even in a language like C++, readability is important. Having large lambdas isn't considered readable. I've seen style guide rules limiting it to 5 or 10 lines. Immediately invoked lambdas have their uses, however, for your example this actually is only overhead from the reader's perspective.

    Go and measure! If you have performance critical code, write a performance test for continuous monitoring and run a profiler from time to time to see where time is spent.