Skip to content

Instantly share code, notes, and snippets.

@outfrost
Last active February 14, 2023 15:20
Show Gist options
  • Save outfrost/ae295e9cf52f995d738f507a4cf95874 to your computer and use it in GitHub Desktop.
Save outfrost/ae295e9cf52f995d738f507a4cf95874 to your computer and use it in GitHub Desktop.
C++ dynamic_cast runtime overhead
/**
* CXXFLAGS := -std=c++17 -O3 -pedantic -Wall -Wextra ${CXXFLAGS}
* LDLIBS := -lstdc++ ${LDLIBS}
*
* Example stderr on AMD Ryzen 7 5800X, with gcc 10.2.1, Linux 4.4.0-19041-Microsoft (WSL, W10 Pro 22H2):
*
* static avg: 64121 ns
* dynamic avg: 75674 ns
*/
#include <chrono>
#include <iostream>
#include <random>
#include <vector>
class Base {
static constexpr int foo = 12;
public:
virtual void exclaim() const {
std::cout << foo << "\n";
}
virtual bool is_sub1() const { return false; }
virtual bool is_sub2() const { return false; }
};
class Sub1 : public Base {
static constexpr int bar = 16384;
public:
void yell() const {
std::cout << bar << "!!!\n";
}
bool is_sub1() const override { return true; }
};
class Sub2 : public Base {
static constexpr int baz = 65536;
public:
void scream() const {
std::cout << baz << "!!!!!!\n";
}
bool is_sub2() const override { return true; }
};
int main() {
using namespace std::chrono;
std::vector<Base*> objects;
srand(time(NULL));
uint64_t total_static = 0;
uint64_t total_dynamic = 0;
constexpr int runs = 256;
for (auto i = 0; i < runs; i++) {
objects.clear();
for (auto i = 0; i < 1024; i++) {
Base* obj;
if (rand() % 2) obj = new Sub1();
else obj = new Sub2();
objects.push_back(obj);
}
time_point start_st = high_resolution_clock::now();
for (const auto obj: objects) {
if (obj->is_sub1()) static_cast<Sub1*>(obj)->yell();
if (obj->is_sub2()) static_cast<Sub2*>(obj)->scream();
}
time_point end_st = high_resolution_clock::now();
total_static += duration_cast<nanoseconds>(end_st - start_st).count();
time_point start_dyn = high_resolution_clock::now();
for (const auto obj : objects) {
const auto sub1 = dynamic_cast<Sub1*>(obj);
if (sub1) sub1->yell();
const auto sub2 = dynamic_cast<Sub2*>(obj);
if (sub2) sub2->scream();
}
time_point end_dyn = high_resolution_clock::now();
total_dynamic += duration_cast<nanoseconds>(end_dyn - start_dyn).count();
}
std::cerr << "static avg: " << total_static / runs << " ns\n";
std::cerr << "dynamic avg: " << total_dynamic / runs << " ns\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment