Last active
December 10, 2023 19:54
-
-
Save SanderMertens/400562cc6f84f74ecccbc0b9967cf62d 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
#include <bench_path.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include "entt.hpp" | |
#define MILLION (1000 * 1000) | |
#define BILLION (1000 * MILLION) | |
#define ENTITY_COUNT (255) | |
#define COMPONENT_COUNT (10) | |
#define QUERY_COUNT (3) | |
#define SAMPLE_COUNT (100) | |
template <int C> | |
struct Type { }; | |
bool flip_coin(void) { | |
int r = rand(); | |
return r >= ((float)RAND_MAX / 2.0f); | |
} | |
void report(const char *query_name, double sum, double min, double max, | |
int64_t entity_count, uint64_t entity_sum) | |
{ | |
sum /= (double)SAMPLE_COUNT; | |
entity_count /= SAMPLE_COUNT; | |
ecs_trace(" total min: %.2fus, avg: %.2fus, max: %.2fus (#[red]%s#[reset])", | |
min * MILLION, sum * MILLION, max * MILLION, query_name, entity_sum); | |
min /= (double)entity_count; | |
sum /= (double)entity_count; | |
max /= (double)entity_count; | |
ecs_trace(" per entity: min: %.2fns, avg: %.2fns, max: %.2fns", | |
min * BILLION, sum * BILLION, max * BILLION); | |
ecs_trace(""); | |
} | |
template <typename ... Types> | |
void bench_view(entt::registry& reg) { | |
auto view = reg.view<Types...>(); | |
/* Warmup */ | |
view.each([&](const auto entity) { }); | |
ecs_time_t t = {0}; | |
uint64_t entity_sum = 0; | |
uint64_t entity_count = 0; | |
double sum = 0, min = 10e10, max = 0; | |
for (int s = 0; s < SAMPLE_COUNT; s ++) { | |
ecs_time_measure(&t); | |
view.each([&](const auto entity) { | |
entity_sum += static_cast<uint64_t>(entity); | |
entity_count ++; | |
}); | |
double v = ecs_time_measure(&t); | |
min = v < min ? v : min; | |
max = v > max ? v : max; | |
sum += v; | |
} | |
report("EnTT - View", sum, min, max, entity_count, entity_sum); | |
} | |
int main(int argc, char *argv[]) { | |
entt::registry reg; | |
ecs_world_t *world = ecs_mini(); | |
ecs_log_set_level(0); | |
ecs_time_t t = {0}; | |
// Create component ids | |
ecs_time_measure(&t); | |
ecs_entity_t *ids = ecs_os_malloc_n(ecs_entity_t, COMPONENT_COUNT); | |
for (int i = 0; i < COMPONENT_COUNT; i ++) { | |
ids[i] = ecs_new_id(world); | |
} | |
// Record table count before creating entities | |
const ecs_world_info_t *info = ecs_get_world_info(world); | |
int32_t table_count = info->table_count; | |
// Create entities | |
for (int i = 0; i < ENTITY_COUNT; i ++) { | |
ecs_entity_t e = ecs_new_id(world); | |
entt::entity entt_e = reg.create(); | |
for (int c = 0; c < COMPONENT_COUNT; c ++) { | |
if (flip_coin()) { | |
ecs_add_id(world, e, ids[c]); | |
switch(c) { | |
case 0: reg.emplace<Type<0>>(entt_e); break; | |
case 1: reg.emplace<Type<1>>(entt_e); break; | |
case 2: reg.emplace<Type<2>>(entt_e); break; | |
case 3: reg.emplace<Type<3>>(entt_e); break; | |
case 4: reg.emplace<Type<4>>(entt_e); break; | |
case 5: reg.emplace<Type<5>>(entt_e); break; | |
case 6: reg.emplace<Type<6>>(entt_e); break; | |
case 7: reg.emplace<Type<7>>(entt_e); break; | |
case 8: reg.emplace<Type<8>>(entt_e); break; | |
case 9: reg.emplace<Type<9>>(entt_e); break; | |
case 10: reg.emplace<Type<10>>(entt_e); break; | |
case 11: reg.emplace<Type<11>>(entt_e); break; | |
case 12: reg.emplace<Type<12>>(entt_e); break; | |
case 13: reg.emplace<Type<13>>(entt_e); break; | |
case 14: reg.emplace<Type<14>>(entt_e); break; | |
case 15: reg.emplace<Type<15>>(entt_e); break; | |
default: ecs_os_abort(); | |
} | |
} | |
} | |
} | |
// Report # of created tables | |
printf("\n"); | |
ecs_trace("entities created: %d (w/%d randomized components)", ENTITY_COUNT, COMPONENT_COUNT); | |
ecs_trace("tables created : %d", info->table_count - table_count); | |
ecs_trace(""); | |
ecs_trace("querying for %d components", QUERY_COUNT); | |
ecs_trace("taking %d samples", SAMPLE_COUNT); | |
ecs_trace(""); | |
// Create query for N components | |
ecs_filter_desc_t fd = { 0 }; | |
for (int i = 0; i < QUERY_COUNT; i ++) { | |
fd.terms[i].id = ids[i]; | |
fd.terms[i].src.flags = EcsSelf; | |
} | |
/* Cached query */ | |
{ | |
ecs_query_desc_t qd = {0}; | |
qd.filter = fd; | |
/* Warmup */ | |
ecs_query_t *f = ecs_query_init(world, &qd); | |
{ | |
ecs_iter_t it = ecs_query_iter(world, f); | |
while ( ecs_query_next(&it) ) { } | |
} | |
uint64_t entity_sum = 0, entity_count = 0; | |
double sum = 0, min = 10e10, max = 0; | |
for (int s = 0; s < SAMPLE_COUNT; s ++) { | |
ecs_iter_t it = ecs_query_iter(world, f); | |
ecs_time_measure(&t); | |
while ( ecs_query_next(&it) ) { | |
for (int i = 0; i < it.count; i ++) { | |
entity_sum += it.entities[i]; | |
entity_count ++; | |
} | |
} | |
double v = ecs_time_measure(&t); | |
min = v < min ? v : min; | |
max = v > max ? v : max; | |
sum += v; | |
} | |
report("Flecs - Cached", sum, min, max, entity_count, entity_sum); | |
ecs_query_fini(f); | |
} | |
/* Uncached query (rule) */ | |
{ | |
/* Warmup */ | |
ecs_rule_t *f = ecs_rule_init(world, &fd); | |
{ | |
ecs_iter_t it = ecs_rule_iter(world, f); | |
while ( ecs_rule_next(&it) ) { } | |
} | |
uint64_t entity_sum = 0, entity_count = 0; | |
double sum = 0, min = 10e10, max = 0; | |
for (int s = 0; s < SAMPLE_COUNT; s ++) { | |
ecs_iter_t it = ecs_rule_iter(world, f); | |
ecs_time_measure(&t); | |
while ( ecs_rule_next_instanced(&it) ) { | |
for (int i = 0; i < it.count; i ++) { | |
entity_sum += it.entities[i]; | |
entity_count ++; | |
} | |
} | |
double v = ecs_time_measure(&t); | |
min = v < min ? v : min; | |
max = v > max ? v : max; | |
sum += v; | |
} | |
report("Flecs - Uncached", sum, min, max, entity_count, entity_sum); | |
ecs_rule_fini(f); | |
} | |
/* EnTT view */ | |
if (QUERY_COUNT == 1) { | |
bench_view<Type<0>>(reg); | |
} else if (QUERY_COUNT == 2) { | |
bench_view<Type<0>, Type<1>>(reg); | |
} else if (QUERY_COUNT == 3) { | |
bench_view<Type<0>, Type<1>, Type<2>>(reg); | |
} else if (QUERY_COUNT == 4) { | |
bench_view<Type<0>, Type<1>, Type<2>, Type<3>>(reg); | |
} else if (QUERY_COUNT == 5) { | |
bench_view<Type<0>, Type<1>, Type<2>, Type<3>, Type<4>>(reg); | |
} else if (QUERY_COUNT == 6) { | |
bench_view<Type<0>, Type<1>, Type<2>, Type<3>, Type<4>, Type<5>>(reg); | |
} | |
ecs_log_set_level(-1); | |
return ecs_fini(world); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment