Skip to content

Instantly share code, notes, and snippets.

@lhchavez
Last active October 21, 2016 22:58
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 lhchavez/2cbc0ffbb4bbee10ebf0c6b77df0cfb7 to your computer and use it in GitHub Desktop.
Save lhchavez/2cbc0ffbb4bbee10ebf0c6b77df0cfb7 to your computer and use it in GitHub Desktop.
// 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