Created
December 21, 2018 12:07
-
-
Save xni/8e1a582e7170818dbc03873083637877 to your computer and use it in GitHub Desktop.
Type introspection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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