Skip to content

Instantly share code, notes, and snippets.

@tamamu
Created March 10, 2021 14:36
Show Gist options
  • Save tamamu/625f045edf76848faeef5d2c58273e51 to your computer and use it in GitHub Desktop.
Save tamamu/625f045edf76848faeef5d2c58273e51 to your computer and use it in GitHub Desktop.
Performance comparison between dynamic-dispatch of virtual function and static function calling in switch clause
#include <iostream>
#include <string>
#include <vector>
#include <chrono>
class Performance
{
private:
std::chrono::system_clock::time_point now;
public:
Performance() {
now = std::chrono::system_clock::now();
}
double check_point() {
std::chrono::system_clock::time_point _now = std::chrono::system_clock::now();
double time = static_cast<double>(
std::chrono::duration_cast<std::chrono::milliseconds>(_now - this->now)
.count() / 1000.0);
now = std::chrono::system_clock::now();
return time;
}
};
/* ----------------------------------------------- */
enum class StructKind {
A,
B
};
struct StructComponent {
StructKind kind;
uint64_t data_index;
};
struct A_StructData {
int32_t count;
};
void A_update(A_StructData& ref) {
std::cerr << ref.count << std::endl;
};
struct B_StructData {
std::string name;
};
void B_update(B_StructData& ref) {
std::cerr << "Hello, " << ref.name << std::endl;
};
class StructBasedSystem {
private:
std::vector<StructComponent> components{};
std::vector<A_StructData> a_data{};
std::vector<B_StructData> b_data{};
public:
void add_A(A_StructData&& data) {
StructComponent com = {StructKind::A, a_data.size()};
a_data.push_back(std::move(data));
components.push_back(com);
}
void add_B(B_StructData&& data) {
StructComponent com = {StructKind::B, b_data.size()};
b_data.push_back(std::move(data));
components.push_back(com);
}
void update() {
for (StructComponent com : components) {
switch (com.kind) {
case StructKind::A:
A_update(a_data[com.data_index]);
break;
case StructKind::B:
B_update(b_data[com.data_index]);
break;
default:
break;
}
}
}
void update2() {
for (A_StructData a : a_data) {
A_update(a);
}
for (B_StructData b : b_data) {
B_update(b);
}
}
};
/* ----------------------------------------------- */
class ClassComponent {
public:
virtual void update()=0;
};
class A_ClassComponent: public ClassComponent {
private:
int32_t count;
public:
A_ClassComponent(int32_t count) : count(count) {}
void update() override {
std::cerr << count++ << std::endl;
}
};
class B_ClassComponent: public ClassComponent {
private:
std::string name;
public:
B_ClassComponent(std::string name) : name(name) {}
void update() override {
std::cerr << "Hello, " << name << std::endl;
}
};
class ClassBasedSystem {
private:
std::vector<ClassComponent*> components{};
public:
void add_component(ClassComponent* com) {
components.push_back(com);
}
void update() {
for (auto com : components) {
com->update();
}
}
};
/* ----------------------------------------------- */
int main() {
StructBasedSystem system1{};
for (int idx = 0; idx < 10000; idx++) {
system1.add_A({idx});
system1.add_B({"name"+std::to_string(idx)});
}
ClassBasedSystem system2{};
for (int idx = 0; idx < 10000; idx++) {
system2.add_component(new A_ClassComponent(idx));
system2.add_component(new B_ClassComponent("name"+std::to_string(idx)));
}
auto perf = Performance{};
perf.check_point();
for (int idx = 0; idx < 100; idx++) system1.update();
auto tm1_1 = perf.check_point();
perf.check_point();
for (int idx = 0; idx < 100; idx++) system1.update2();
auto tm1_2 = perf.check_point();
perf.check_point();
for (int idx = 0; idx < 100; idx++) system2.update();
auto tm2 = perf.check_point();
std::cout << tm1_1 << std::endl << tm1_2 << std::endl << tm2 << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment