Skip to content

Instantly share code, notes, and snippets.

@xni
Created December 21, 2018 12:07
Show Gist options
  • Save xni/8e1a582e7170818dbc03873083637877 to your computer and use it in GitHub Desktop.
Save xni/8e1a582e7170818dbc03873083637877 to your computer and use it in GitHub Desktop.
Type introspection
#include <cstdlib>
#include <cstdio>
#include <chrono>
#include <variant>
#include <vector>
#include <typeinfo>
#include <type_traits>
using Clock = std::chrono::high_resolution_clock;
enum class Tag { Base, Derived };
class Base {
public:
virtual ~Base() = default;
virtual Tag GetTag() const { return Tag::Base; }
};
class Derived : public Base {
public:
virtual Tag GetTag() const { return Tag::Derived; }
};
class NVBase {
void Do();
};
class NVDerived {
void Do();
};
using NVContainer = std::variant<NVBase, NVDerived>;
void BaseLine(const std::vector<int>& data) {
int bases = 0;
int deriveds = 0;
auto t1 = Clock::now();
for (int i = 0; i < data.size(); ++i) {
if (data[i])
++bases;
else
++deriveds;
}
auto t2 = Clock::now();
std::printf("BaseLine,0,%lld,%d,%d\n", (t2 - t1).count(), bases, deriveds);
}
void TypeOf(const std::vector<Base*>& data) {
int bases = 0;
int deriveds = 0;
auto t1 = Clock::now();
for (int i = 0; i < data.size(); ++i) {
auto& item = *data[i];
if (typeid(item) == typeid(Base))
++bases;
else
++deriveds;
}
auto t2 = Clock::now();
std::printf("TypeOf,1,%lld,%d,%d\n", (t2 - t1).count(), bases, deriveds);
}
void DynamicCast(const std::vector<Base*>& data) {
int bases = 0;
int deriveds = 0;
auto t1 = Clock::now();
for (int i = 0; i < data.size(); ++i) {
if (dynamic_cast<Derived*>(data[i]) != nullptr)
++deriveds;
else
++bases;
}
auto t2 = Clock::now();
std::printf("DynamicCast,2,%lld,%d,%d\n", (t2 - t1).count(), bases, deriveds);
}
void VirtualFunction(const std::vector<Base*>& data) {
int bases = 0;
int deriveds = 0;
auto t1 = Clock::now();
for (int i = 0; i < data.size(); ++i) {
switch (data[i]->GetTag()) {
case Tag::Base:
++bases;
break;
default:
++deriveds;
}
}
auto t2 = Clock::now();
std::printf("VirtualFunction,3,%lld,%d,%d\n", (t2 - t1).count(), bases, deriveds);
}
void Variant(const std::vector<NVContainer>& data) {
int bases = 0;
int deriveds = 0;
auto t1 = Clock::now();
for (int i = 0; i < data.size(); ++i) {
if (std::holds_alternative<NVBase>(data[i]))
++bases;
else
++deriveds;
}
auto t2 = Clock::now();
std::printf("Variant,4,%lld,%d,%d\n", (t2 - t1).count(), bases, deriveds);
}
int main(int argc, const char** argv) {
if (argc != 2) {
std::printf("USAGE: %s SIZE\n", argv[0]);
return 1;
}
const size_t size = std::atol(argv[1]);
std::vector<Base*> base_data(size);
std::vector<int> bool_data(size);
std::vector<NVContainer> variant_data(size);
for (int i = 0; i < size; ++i) {
const bool choice = std::rand() % 2;
bool_data[i] = choice;
if (choice) {
base_data[i] = new Base();
variant_data[i] = NVBase();
} else {
base_data[i] = new Derived();
variant_data[i] = NVDerived();
}
}
for (int j = 0; j < 10; ++j) {
for (int i = 0; i < 10; ++i) {
BaseLine(bool_data);
}
for (int i = 0; i < 10; ++i) {
TypeOf(base_data);
}
for (int i = 0; i < 10; ++i) {
DynamicCast(base_data);
}
for (int i = 0; i < 10; ++i) {
VirtualFunction(base_data);
}
for (int i = 0; i < 10; ++i) {
Variant(variant_data);
}
}
for (int i = 0; i < size; ++i) {
delete base_data[i];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment