Skip to content

Instantly share code, notes, and snippets.

@esprehn
Created October 16, 2015 01:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save esprehn/c6fa65eac153028ab1a3 to your computer and use it in GitHub Desktop.
Save esprehn/c6fa65eac153028ab1a3 to your computer and use it in GitHub Desktop.
Virtual vs Switch
// Sample virtual vs switch, compiled with
// clang++ -std=c++11 -O3 benchmark.cpp
//
// Tested on a MBP:
//
// Computed 33332
// virtual loop(474 ticks, 0.000474 seconds)
// Computed 33332
// switch loop(173 ticks, 0.000173 seconds)
#include <iostream>
#include <ctime>
#include <vector>
class Base {
public:
virtual int test(int value) = 0;
};
class SubA : public Base {
int test(int value) override;
};
__attribute__((noinline))
int SubA::test(int value) { return value + 1; }
__attribute__((noinline))
int applyA(int value) { return value + 1; }
class SubB : public Base {
int test(int value) override;
};
__attribute__((noinline))
int SubB::test(int value) { return value - 1; }
__attribute__((noinline))
int applyB(int value) { return value - 1; }
class SubC : public Base {
int test(int value) override;
};
__attribute__((noinline))
int SubC::test(int value) { return value + 2; }
__attribute__((noinline))
int applyC(int value) { return value + 2; }
enum TypeId {
TypeA,
TypeB,
TypeC,
MaxTypeId,
};
TypeId toTypeId(int i)
{
return static_cast<TypeId>(i % MaxTypeId);
}
Base* createObject(int i)
{
switch (toTypeId(i)) {
case TypeA:
return new SubA();
case TypeB:
return new SubB();
case TypeC:
return new SubC();
default:
std::cout << "ERROR!" << std::endl;
return nullptr;
}
}
class Benchmark {
public:
Benchmark(const std::string& name)
: m_time(clock())
, m_name(name)
{ }
~Benchmark()
{
time_t delta = clock() - m_time;
std::cout
<< m_name
<< "("
<< delta
<< " ticks, "
<< ((float)delta)/CLOCKS_PER_SEC
<< " seconds)"
<< std::endl;
}
private:
clock_t m_time;
std::string m_name;
};
int main()
{
{
std::vector<Base*> items;
for (int i = 0; i < 50000; ++i) {
items.push_back(createObject(i));
}
Benchmark bm("virtual loop");
int value = 0;
for (int i = 0; i < 50000; ++i) {
value = items[i]->test(value);
}
std::cout << "Computed " << value << std::endl;
}
{
std::vector<TypeId> items;
for (int i = 0; i < 50000; ++i) {
items.push_back(toTypeId(i));
}
Benchmark bm("switch loop");
int value = 0;
for (int i = 0; i < 50000; ++i) {
switch (toTypeId(i)) {
case TypeA:
value = applyA(value);
break;
case TypeB:
value = applyB(value);
break;
case TypeC:
value = applyC(value);
break;
default:
std::cout << "ERROR!" << std::endl;
}
}
std::cout << "Computed " << value << std::endl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment