jeudi 24 décembre 2020

Is there call overhead if std::bind is used in recursive way?

I'm writing a template function which involved usage of f = std::bind(std::bind(std::bind(...))).

but I'm not sure whether the c++ compiler is smart enough to unfold the calling chain.
What I mean is:

  1. when creating functor f, is there multiple std::bind() invoked at runtime?
  2. when calling f(), does it involves calling multiple operator() at different layers of bind_functor object.

As a simple example: Does f2() run slightly faster than f1()?

#include <functional>

int add(int a, int b) {
  return a + b;
}

int main() {
  using namespace std::placeholders;
  auto f1 = std::bind(std::bind(&add, 1, _1), 2);
  auto f2 = std::bind(&add, 1, 2);
  return 0;
}

Update: I did some experiment. It seems f2() does run faster than f1(). And if you use std::function, it is even slower. Here is the experimental code (ubuntu/gcc 7.5.0, with optimization enabled. Without optimization, f2 is the slowest.):

#include <chrono>
#include <iostream>
#include <functional>

int add(int a, int b) {
  return a + b;
}

int main() {
  using namespace std::placeholders;
  auto f1 = std::bind(std::bind(&add, 1, _1), 2);
  auto f2 = std::bind(&add, 1, 2);
  std::function<int(void)> f3 = std::bind(&add, 1, 2);
  const int N = 10000000;

  {
    auto begin = std::chrono::system_clock::now();
    for (int n = 0; n < N; n++) {
      f1();
    }
    auto end = std::chrono::system_clock::now();
    auto d = end - begin;
    std::cout << "done: " << d.count() << std::endl;
  }

  {
    auto begin = std::chrono::system_clock::now();
    for (int n = 0; n < N; n++) {
      f2();
    }
    auto end = std::chrono::system_clock::now();
    auto d = end - begin;
    std::cout << "done: " << d.count() << std::endl;
  }

  {
    auto begin = std::chrono::system_clock::now();
    for (int n = 0; n < N; n++) {
      f3();
    }
    auto end = std::chrono::system_clock::now();
    auto d = end - begin;
    std::cout << "done: " << d.count() << std::endl;
  }

  return 0;
}

Aucun commentaire:

Enregistrer un commentaire