Last active
October 21, 2016 22:58
-
-
Save lhchavez/2cbc0ffbb4bbee10ebf0c6b77df0cfb7 to your computer and use it in GitHub Desktop.
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
// Benchmark Time CPU Iterations | |
// ----------------------------------------------------- | |
// BM_DynamicCast 1073 ns 1074 ns 630631 | |
// BM_StaticCast 452 ns 452 ns 1552106 | |
// BM_TaggedCast 59 ns 59 ns 11111111 | |
#include <assert.h> | |
#include <stddef.h> | |
#include <stdint.h> | |
#include <benchmark/benchmark.h> | |
#include <algorithm> | |
#include <memory> | |
#include <random> | |
#include <vector> | |
class Object { | |
public: | |
Object() = default; | |
virtual ~Object() = default; | |
virtual size_t tag() const = 0; | |
}; | |
class DynA : public Object { | |
public: | |
DynA() = default; | |
~DynA() override = default; | |
size_t tag() const override { return 1; } | |
}; | |
class DynB : public Object { | |
public: | |
DynB() = default; | |
~DynB() override = default; | |
size_t tag() const override { return 2; } | |
}; | |
class TaggedHolder { | |
public: | |
TaggedHolder(std::unique_ptr<Object> o) : tag_(o->tag()), o_(std::move(o)) {} | |
size_t tag() const { return tag_; } | |
DynA* a() const { | |
if (tag_ == 1) return static_cast<DynA*>(o_.get()); | |
return nullptr; | |
} | |
DynB* b() const { | |
if (tag_ == 2) return static_cast<DynB*>(o_.get()); | |
return nullptr; | |
} | |
private: | |
const size_t tag_; | |
const std::unique_ptr<Object> o_; | |
}; | |
std::vector<std::unique_ptr<Object>> fill() { | |
std::vector<std::unique_ptr<Object>> v; | |
for (size_t i = 0; i < 100; i++) { | |
if (i % 2 == 0) { | |
v.emplace_back(new DynA()); | |
} else { | |
v.emplace_back(new DynB()); | |
} | |
} | |
return v; | |
} | |
static void BM_DynamicCast(benchmark::State& state) { | |
std::vector<std::unique_ptr<Object>> v = fill(); | |
while (state.KeepRunning()) { | |
size_t cnt = 0; | |
for (const auto& o : v) { | |
DynA* a = dynamic_cast<DynA*>(o.get()); | |
if (a != nullptr) { | |
cnt++; | |
} | |
} | |
assert(cnt == 50); | |
} | |
} | |
BENCHMARK(BM_DynamicCast); | |
static void BM_StaticCast(benchmark::State& state) { | |
std::vector<std::unique_ptr<Object>> v = fill(); | |
while (state.KeepRunning()) { | |
size_t cnt = 0; | |
for (const auto& o : v) { | |
if (o->tag() == 1) { | |
cnt++; | |
} | |
} | |
assert(cnt == 50); | |
} | |
} | |
BENCHMARK(BM_StaticCast); | |
static void BM_TaggedCast(benchmark::State& state) { | |
std::vector<std::unique_ptr<TaggedHolder>> v; | |
for (size_t i = 0; i < 100; i++) { | |
if (i % 2 == 0) { | |
v.emplace_back(new TaggedHolder(std::unique_ptr<Object>(new DynA()))); | |
} else { | |
v.emplace_back(new TaggedHolder(std::unique_ptr<Object>(new DynB()))); | |
} | |
} | |
while (state.KeepRunning()) { | |
size_t cnt = 0; | |
for (const auto& o : v) { | |
if (o->a() != nullptr) { | |
cnt++; | |
} | |
} | |
assert(cnt == 50); | |
} | |
} | |
BENCHMARK(BM_TaggedCast); | |
BENCHMARK_MAIN(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment