Created
March 10, 2021 14:36
-
-
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
This file contains hidden or 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 <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