Polymorphism with std::variant perfomances

Viewed 118

Having a closer look at __do_visit in std::variant I grew curious about the performances of the std::variant polymorphic approach

I wrote a small test program to compare old school inheritance to the std::variant one

#include <variant>
#include <vector>
#include <iostream>
#include <string>
#include <chrono>

int i = 0;
// Polymorphism using variants
class circle
{
  public:
    void draw() const { i++; }
};

class line
{
  public:
    void draw() const { i++; }
};
using v_t  = std::variant<circle, line>;

void variant_way(const std::vector<v_t>& v)
{
  for (const auto &var : v)
    std::visit([](const auto& o) {
        o.draw();
        }, var);
}

// old school
class shape
{
  public:
    virtual void draw() const = 0;
    virtual ~shape() { }
};
class circle_in : public shape
{
  public:
    virtual void draw() const { i++; }
};

class line_in : public shape
{
  public:
   virtual void draw() const { i++; }
};

void inherit_way(const std::vector<shape*>& v)
{
  for (const auto var : v)
        var->draw();
}

// call and measure
template <typename F, typename D>
void run(F f, const D& data, std::string name)
{
  auto start = std::chrono::high_resolution_clock::now();
  f(data);
  auto end = std::chrono::high_resolution_clock::now();
  auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
  std::cout << name << ": "<< elapsed.count() << std::endl;
}

int main()
{
  constexpr int howmany = 100000;
  {
    std::vector<v_t> v {howmany};
    run(variant_way, v, "variant");
  }
  {
    std::vector<shape*> v;
    for (int i = 0; i < howmany; i++)
      v.push_back(new circle_in());
    run(inherit_way, v, "inherit_way");
    // deallocate
  }
  return 0;
}

On my machine (i7, 16GB RAM), I get these results:

variant: 7487
inherit_way: 1302

I suspect that this result reflects the fact that the std::variant approach creates the vtable at each iteration while the inheriting approach does it once for all.

Is this explanation correct?

Is there a way to reduce the overhead?

0 Answers
Related