lundi 1 février 2016

Template code way slower than regular

So I was looking at this blog post (http://ift.tt/14JBVnm), which is a very nice blog post! And I wrote the following test case to test this out for myself

#include <iostream>

const unsigned N = 40000;

/******************************************************************************
 * A Regular class
 * ****************************************************************************/
class Regular {
public:
    void tick(uint64_t n) {
        this->counter += n;
    }

    uint64_t getvalue() {
        return this->counter;
    }

private:
    uint64_t counter;
};
void run_reg(Regular* obj) {
  for (unsigned i = 0; i < N; ++i) {
    for (unsigned j = 0; j < i; ++j) {
      obj->tick(j);
    }
  }
}
/******************************************************************************
 * A regular class
 * ****************************************************************************/


/******************************************************************************
 * A polymorphic base class
 * ****************************************************************************/
class DynamicInterface {
public:
  virtual void tick(uint64_t n) = 0;
  virtual uint64_t getvalue() = 0;
};

class DynamicImplementation : public DynamicInterface {
  uint64_t counter;

public:
  DynamicImplementation()
    : counter(0) {
  }

  virtual void tick(uint64_t n) {
    counter += n;
  }

  virtual uint64_t getvalue() {
    return counter;
  }
};


void run_dynamic(DynamicInterface* obj) {
  for (unsigned i = 0; i < N; ++i) {
    for (unsigned j = 0; j < i; ++j) {
      obj->tick(j);
    }
  }
}
/******************************************************************************
 * A polymorphic base class
 * ****************************************************************************/


/******************************************************************************
 * A templated interface
 * ****************************************************************************/
template <typename Implementation>
class CRTPInterface {
public:
  void tick(uint64_t n) {
    impl().tick(n);
  }

  uint64_t getvalue() {
    return impl().getvalue();
  }
private:
  Implementation& impl() {
    return *static_cast<Implementation*>(this);
  }
};

class CRTPImplementation : public CRTPInterface<CRTPImplementation> {
  uint64_t counter;
public:
  CRTPImplementation()
    : counter(0) {
  }

  void tick(uint64_t n) {
    counter += n;
  }

  uint64_t getvalue() {
    return counter;
  }
};

template <typename Implementation>
void run_crtp(CRTPInterface<Implementation>* obj) {
  for (unsigned i = 0; i < N; ++i) {
    for (unsigned j = 0; j < i; ++j) {
      obj->tick(j);
    }
  }
}
/******************************************************************************
 * A templated interface
 * ****************************************************************************/

int main() {

#if defined(TEMPLATE)
    CRTPInterface<CRTPImplementation> obj;
    run_crtp(&obj);
#elif defined(DYNAMIC)
    DynamicInterface* dynamic_interface_obj = new DynamicImplementation();
    run_dynamic(dynamic_interface_obj);
#else
    Regular reg;
    run_reg(&reg);
#endif

    return 0;
}

The results were surprising! On my machine (which is a MacBook Pro 13 inch with Retina Display, and compiled with clang-700.1.81) the regular one took 2.668s to run, the polymorphic version took 2.665s and the templated version took 5.861s to complete. Could someone shed some light on why this is?

The commands used to compile were

g++ -std=c++11 test_polymorphic.cpp 
g++ -std=c++11 test_polymorphic.cpp -DDYNAMIC
g++ -std=c++11 test_polymorphic.cpp -DTEMPLATE

Thanks!

Aucun commentaire:

Enregistrer un commentaire