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
------------------------------------