Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is std::function heavier than auto storing lambda function

I heard that cost of std::function is heavier than auto to deal with a lambda function. effective modern c++ item5. What I want is to clarify the mechanism why std::function use more memory than auto with some sample code. Could somebody help me?

edit

class Widget {
public:
  Widget(int i) : i_(i) {}
  bool operator<(const Widget& o) { return o.value() > i_; }
  int value() const { return i_; };
private:
  int i_;
  int dummy_[1024];
};

int main() {
  // performance difference between auto and std::function
  { 
    auto less1 = [](const auto& p1, const auto& p2) {
      return *p1 < *p2;
    };
    std::cout << "size of less1: " << sizeof(less1) << endl;

    function<bool(const std::unique_ptr<Widget>&,
                  const std::unique_ptr<Widget>&)>
        less2 = [](const std::unique_ptr<Widget>& p1,
                   const std::unique_ptr<Widget>& p2) {
          return *p1 < *p2;
        };
    std::cout << "size of less2: " << sizeof(less2) << endl;

    {
      // auto
      std::vector<std::unique_ptr<Widget>> ws1;
      for (auto i = 0; i < 1024*100; ++i) {
        ws1.emplace_back(new Widget(std::rand()));
      }

      auto start = std::chrono::high_resolution_clock::now();
      std::sort(ws1.begin(), ws1.end(), less1);
      auto end = std::chrono::high_resolution_clock::now();
      cout << ws1[0].get()->value() << " time: " << (end - start).count() << endl;
    }

    {
      // std::function
      // 25% slower than using auto
      std::vector<std::unique_ptr<Widget>> ws2;
      for (auto i = 0; i < 1024*100; ++i) {
        ws2.emplace_back(new Widget(std::rand()));
      }

      auto start = std::chrono::high_resolution_clock::now();
      std::sort(ws2.begin(), ws2.end(), less2);
      auto end = std::chrono::high_resolution_clock::now();
      cout << ws2[0].get()->value() << " time: " << (end - start).count() << endl;
    }
  }
  return 0;
}

it's from https://github.com/danielhongwoo/mec/blob/master/item5/item5.cpp

I think this code shows me using std::function is slower than using auto. But not usage of memory. I just want to prove it with some real code.

like image 606
Daniel Lee Avatar asked Dec 28 '17 12:12

Daniel Lee


People also ask

Is std :: function heavy?

Note that when talking about overhead of std::function (i.e. that std::function is "heavy"), usually the performance overhead is meant. Its memory overhead will be minor (around 2 extra pointers, I'd guess).

Are lambda functions faster in C++?

sorting - Why is a C++ Lambda function much faster as compare function than an equivalent object - Stack Overflow. Stack Overflow for Teams – Start collaborating and sharing organizational knowledge.

Can std :: function store lambda?

Instances of std::function can store, copy, and invoke any CopyConstructible Callable target -- functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.

What is the difference between functor and lambda?

The Functor is self-documenting by default; but Lambda's need to be stored in variables (to be self-documenting) inside more-complex algorithm definitions.

What are the performance implications of using a lambda function?

There are two performance implications of using std::function that might surprise you: When calling a std::function, it does a virtual function call. When assigning a lambda with significant captures to a std::function, it will do a dynamic memory allocation!

Why are lambda functions faster in C++ than C?

Because they are objects rather than pointers they can be inlined very easily by the compiler, much like functors. This means that calling a lambda many times (such as with std::sort or std::copy_if) is much better than using a global function. This is one example of where C++ is actually faster than C.

How to make a function accept both Lambda and Lambda2?

To make func accepts both lambda and lambda2 , std::function needs to have constructors that take any function object or plain function that satisfies its signature. And we need to perform type erasure to achieve this behavior. There are various techniques to implement type erasure in C++, and it is not a topic I can fit into this post.

What is the difference between a global function and a Lambda?

This means that calling a lambda many times (such as with std::sort or std::copy_if) is much better than using a global function. This is one example of where C++ is actually faster than C. std::function is a templated object that is used to store and call any callable type, such as functions, objects, lambdas and the result of std::bind.


1 Answers

std::function can store an arbitrary callable. In therefore has to engage in type erasure to be able to store something of an arbitrary type. This can require dynamic allocation in the general case, and it definitely requires an indirect call (either a virtual call or a call through a function pointer) on each invocation of operator ().

The type of a lambda expression is not std::function, it's an unnamed class type with operator() defined (the lambda's closure type). Using auto a to store a lambda makes the type of a this precise closure type, which has no overhead.

like image 181
Angew is no longer proud of SO Avatar answered Oct 04 '22 10:10

Angew is no longer proud of SO