HOME

Performance test

#include "stdafx.h"
#include <typeinfo>
#include <cassert>
#include <vector>
#include <memory>
#include <iostream>
#include "Stopwatch.h"

int boxCount = 0;
int circleCount = 0;
int ellipseCount = 0;

void ClearCount()
{
  boxCount = 0;
  circleCount = 0;
  ellipseCount = 0;
}

void PrintCount()
{
  std::cout << "box count = " << boxCount << std::endl;
  std::cout << "circle count = " << circleCount << std::endl;
  std::cout << "ellipse count = " << ellipseCount << std::endl;
  std::cout << "------------------------------------" << std::endl;
  std::cout << std::endl;
}

struct TBox;
struct TCircle;
struct TEllipse;

struct ShapeVisitor
{
  virtual void Visit(TBox&) = 0;
  virtual void Visit(TCircle&) = 0;
  virtual void Visit(TEllipse&) = 0;
};


struct Shape
{
  virtual ~Shape() {};
  virtual void Accept(ShapeVisitor&) = 0;
  virtual void VirtualDraw() = 0;
};

struct TBox : public Shape
{
  int m_boxint;
  TBox()
  {
    m_boxint = 1;
  }

  virtual  void Accept(ShapeVisitor& shapeVisitor) override
  {
    shapeVisitor.Visit(*this);
  }
  virtual void VirtualDraw() override
  {
    boxCount++;
  }
};

struct TCircle : public Shape
{
  int m_circleint;
  TCircle()
  {
    m_circleint = 1;
  }

  virtual  void Accept(ShapeVisitor& shapeVisitor) override
  {
    shapeVisitor.Visit(*this);
  }
  virtual void VirtualDraw() override
  {
    circleCount++;
  }
};

struct TEllipse : public Shape
{
  int m_ellipseint;
  TEllipse()
  {
    m_ellipseint = 1;
  }

  virtual void Accept(ShapeVisitor& shapeVisitor) override
  {
    shapeVisitor.Visit(*this);
  }

  virtual void VirtualDraw() override
  {
    ellipseCount++;
  }
};


void Draw(TBox& box)
{
  boxCount += box.m_boxint;
}

void Draw(TCircle& circle)
{
  circleCount += circle.m_circleint;
}

void Draw(TEllipse& ellipse)
{
  ellipseCount += ellipse.m_ellipseint;
}

struct DrawVisitor : public ShapeVisitor
{
  virtual void Visit(TBox& obj) override
  {
    Draw(obj);
  }
  virtual void Visit(TCircle& obj) override
  {
    Draw(obj);
  }
  virtual void Visit(TEllipse& obj) override
  {
    Draw(obj);
  }
};

void DrawTypeId(Shape& shape)
{
  if (typeid(shape) == typeid(TBox))
  {
    Draw(dynamic_cast<TBox&>(shape));
  }
  else if (typeid(shape) == typeid(TCircle))
  {
    Draw(dynamic_cast<TCircle&>(shape));
  }
  else if (typeid(shape) == typeid(TEllipse))
  {
    Draw(dynamic_cast<TEllipse&>(shape));
  }
  else
  {
    assert(false);
  }
}

void DrawDynamicCast(Shape& shape)
{
  if (auto p = dynamic_cast<TBox*>(&shape))
  {
    Draw(*p);
  }
  else if (auto p = dynamic_cast<TCircle*>(&shape))
  {
    Draw(*p);
  }
  else if (auto p = dynamic_cast<TEllipse*>(&shape))
  {
    Draw(*p);
  }
  else
  {
    assert(false);
  }
}

void CreateShapes(std::vector<std::unique_ptr<Shape>>& shapes)
{
  for (int i = 0; i < 1000; i++)
  {
    if (i % 2 == 0)
    {
      shapes.emplace_back(std::unique_ptr<TBox>(new TBox));
    }
    else if (i % 3 == 0)
    {
      shapes.emplace_back(std::unique_ptr<TCircle>(new TCircle));
    }
    else if (i % 5 == 0)
    {
      shapes.emplace_back(std::unique_ptr<TEllipse>(new TEllipse));
    }
  }

}

int main()
{
  std::vector<std::unique_ptr<Shape>> shapes;

  CreateShapes(shapes);
  ClearCount();

  Stopwatch sw(true);

  for (size_t i = 0; i < shapes.size(); i++)
  {
    DrawTypeId(*shapes[i].get());
  }




  sw.Stop();
  std::cout << "Using typeid + dynamic_cast" << std::endl;
  std::cout <<  sw << std::endl;
  PrintCount();

  /////////////////
  ClearCount();
  sw.Start();

  for (size_t i = 0; i < shapes.size(); i++)
  {
    shapes[i]->VirtualDraw();
  }

  sw.Stop();
  std::cout << "Using virtual function" << std::endl;
  std::cout <<  sw << std::endl;
  PrintCount();
  //////////////////////

  /////////////////
  ClearCount();
  sw.Start();

  for (size_t i = 0; i < shapes.size(); i++)
  {
    DrawDynamicCast(*shapes[i].get());
  }

  sw.Stop();
  std::cout << "Using dynamic_cast" << std::endl;
  std::cout <<  sw << std::endl;
  PrintCount();
  //////////////////////
  ClearCount();

  DrawVisitor drawVisitor;
  sw.Start();

  for (size_t i = 0; i < shapes.size(); i++)
  {
    shapes[i]->Accept(drawVisitor);
  }

  sw.Stop();

  std::cout << "Using visitor pattern" << std::endl;
  std::cout <<  sw << std::endl;

  PrintCount();

  return 0;
}


Results - Visual C++ 2012

Using typeid + dynamic_cast
397 ticks, 0 ms
box count = 500
circle count = 167
ellipse count = 67
------------------------------------

Using virtual function
90555 ticks, 35 ms
box count = 500
circle count = 167
ellipse count = 67
------------------------------------

Using dynamic_cast
217489 ticks, 85 ms
box count = 500
circle count = 167
ellipse count = 67
------------------------------------

Using visitor pattern
329539 ticks, 129 ms
box count = 500
circle count = 167
ellipse count = 67
------------------------------------