From f9ac2aa02a70dc06b6ae03694bcb04dca7c21c8a Mon Sep 17 00:00:00 2001 From: Sander Mertens Date: Thu, 29 Aug 2024 15:41:09 -0700 Subject: [PATCH] Add performance tracing hooks to Flecs (#1326) Summary: Pull Request resolved: https://github.com/SanderMertens/flecs/pull/1326 This change adds performance tracing hooks to the OS API which allows Flecs to be used with profilers like Tracy. Reviewed By: Jason-M-Fugate Differential Revision: D61947598 Privacy Context Container: L1120261 --- distr/flecs.c | 87 +++++++++++++++---- distr/flecs.h | 35 ++++++++ include/flecs.h | 1 + include/flecs/addons/system.h | 3 + include/flecs/os_api.h | 31 +++++++ src/addons/system/system.c | 9 ++ src/entity.c | 15 +++- src/observable.c | 4 + src/os_api.c | 20 +++++ src/query/engine/cache.c | 4 + src/storage/table.c | 4 + src/storage/table_graph.c | 4 + src/world.c | 27 +++--- .../c/perf_trace/include/perf_trace.h | 16 ++++ .../include/perf_trace/bake_config.h | 24 +++++ test/custom_builds/c/perf_trace/project.json | 14 +++ test/custom_builds/c/perf_trace/src/main.c | 40 +++++++++ 17 files changed, 308 insertions(+), 30 deletions(-) create mode 100644 test/custom_builds/c/perf_trace/include/perf_trace.h create mode 100644 test/custom_builds/c/perf_trace/include/perf_trace/bake_config.h create mode 100644 test/custom_builds/c/perf_trace/project.json create mode 100644 test/custom_builds/c/perf_trace/src/main.c diff --git a/distr/flecs.c b/distr/flecs.c index d6f1bf3b2a..604ece7aaf 100644 --- a/distr/flecs.c +++ b/distr/flecs.c @@ -5430,11 +5430,13 @@ void flecs_instantiate( ecs_id_record_t *idr = flecs_id_record_get(world, ecs_childof(base)); ecs_table_cache_iter_t it; if (idr && flecs_table_cache_all_iter((ecs_table_cache_t*)idr, &it)) { + ecs_os_perf_trace_push("flecs.instantiate"); const ecs_table_record_t *tr; while ((tr = flecs_table_cache_next(&it, ecs_table_record_t))) { flecs_instantiate_children( world, base, table, row, count, tr->hdr.table); } + ecs_os_perf_trace_pop("flecs.instantiate"); } } @@ -5858,6 +5860,8 @@ void flecs_commit( return; } + ecs_os_perf_trace_push("flecs.commit"); + if (src_table) { ecs_assert(dst_table != NULL, ECS_INTERNAL_ERROR, NULL); flecs_table_traversable_add(dst_table, is_trav); @@ -5893,7 +5897,9 @@ void flecs_commit( ECS_OUT_OF_RANGE, 0); ecs_check(entity >= world->info.min_id, ECS_OUT_OF_RANGE, 0); - } + } + + ecs_os_perf_trace_pop("flecs.commit"); error: flecs_journal_end(); @@ -7720,6 +7726,8 @@ void ecs_delete( return; } + ecs_os_perf_trace_push("flecs.delete"); + ecs_record_t *r = flecs_entities_try(world, entity); if (r) { flecs_journal_begin(world, EcsJournalDelete, entity, NULL, NULL); @@ -7768,6 +7776,7 @@ void ecs_delete( flecs_defer_end(world, stage); error: + ecs_os_perf_trace_pop("flecs.delete"); return; } @@ -9939,6 +9948,8 @@ bool flecs_defer_end( ecs_assert(stage->defer > 0, ECS_INTERNAL_ERROR, NULL); if (!--stage->defer) { + ecs_os_perf_trace_push("flecs.commands.merge"); + /* Test whether we're flushing to another queue or whether we're * flushing to the storage */ bool merge_to_world = false; @@ -10133,6 +10144,8 @@ bool flecs_defer_end( } } + ecs_os_perf_trace_pop("flecs.commands.merge"); + return true; } @@ -13473,6 +13486,8 @@ void flecs_emit( ecs_check(desc->table != NULL, ECS_INVALID_PARAMETER, NULL); ecs_check(desc->observable != NULL, ECS_INVALID_PARAMETER, NULL); + ecs_os_perf_trace_push("flecs.emit"); + ecs_time_t t = {0}; bool measure_time = world->flags & EcsWorldMeasureSystemTime; if (measure_time) { @@ -13797,6 +13812,8 @@ void flecs_emit( error: world->stages[0]->defer = defer; + ecs_os_perf_trace_pop("flecs.emit"); + if (measure_time) { world->info.emit_time_total += (ecs_ftime_t)ecs_time_measure(&t); } @@ -15417,6 +15434,26 @@ void ecs_os_strset(char **str, const char *value) { ecs_os_free(old); } +void ecs_os_perf_trace_push_( + const char *file, + size_t line, + const char *name) +{ + if (ecs_os_api.perf_trace_push_) { + ecs_os_api.perf_trace_push_(file, line, name); + } +} + +void ecs_os_perf_trace_pop_( + const char *file, + size_t line, + const char *name) +{ + if (ecs_os_api.perf_trace_pop_) { + ecs_os_api.perf_trace_pop_(file, line, name); + } +} + /* Replace dots with underscores */ static char *module_file_base(const char *module, char sep) { @@ -17801,6 +17838,8 @@ void flecs_eval_component_monitor( return; } + ecs_os_perf_trace_push("flecs.component_monitor.eval"); + world->monitors.is_dirty = false; ecs_map_iter_t it = ecs_map_iter(&world->monitors.monitors); @@ -17822,6 +17861,8 @@ void flecs_eval_component_monitor( }); } } + + ecs_os_perf_trace_pop("flecs.component_monitor.eval"); } void flecs_monitor_mark_dirty( @@ -19359,6 +19400,8 @@ void flecs_process_pending_tables( return; } + ecs_os_perf_trace_push("flecs.process_pending_tables"); + flecs_journal_begin(world, EcsJournalTableEvents, 0, 0, 0); do { @@ -19413,6 +19456,8 @@ void flecs_process_pending_tables( } while ((count = flecs_sparse_count(world->pending_tables))); flecs_journal_end(); + + ecs_os_perf_trace_pop("flecs.process_pending_tables"); } void flecs_table_set_empty( @@ -19472,11 +19517,13 @@ int32_t ecs_delete_empty_tables( { flecs_poly_assert(world, ecs_world_t); + ecs_os_perf_trace_push("flecs.delete_empty_tables"); + /* Make sure empty tables are in the empty table lists */ ecs_run_aperiodic(world, EcsAperiodicEmptyTables); ecs_time_t start = {0}, cur = {0}; - int32_t delete_count = 0, clear_count = 0; + int32_t delete_count = 0; bool time_budget = false; if (ECS_NEQZERO(time_budget_seconds) || (ecs_should_log_1() && ecs_os_has_time())) { @@ -19515,24 +19562,13 @@ int32_t ecs_delete_empty_tables( flecs_table_fini(world, table); delete_count ++; } else if (clear_generation && (gen > clear_generation)) { - if (flecs_table_shrink(world, table)) { - clear_count ++; - } + flecs_table_shrink(world, table); } } } done: - if (ecs_should_log_1() && ecs_os_has_time()) { - if (delete_count) { - ecs_dbg_1("#[red]deleted#[normal] %d empty tables in %.2fs", - delete_count, ecs_time_measure(&start)); - } - if (clear_count) { - ecs_dbg_1("#[red]cleared#[normal] %d empty tables in %.2fs", - clear_count, ecs_time_measure(&start)); - } - } + ecs_os_perf_trace_pop("flecs.delete_empty_tables"); return delete_count; } @@ -36799,6 +36835,8 @@ void flecs_table_fini( ECS_INTERNAL_ERROR, NULL); (void)world; + ecs_os_perf_trace_push("flecs.table.free"); + if (!is_root && !(world->flags & EcsWorldQuit)) { if (table->flags & EcsTableHasOnTableDelete) { flecs_table_emit(world, table, EcsOnTableDelete); @@ -36849,6 +36887,8 @@ void flecs_table_fini( } ecs_log_pop_2(); + + ecs_os_perf_trace_pop("flecs.table.free"); } /* Free table type. Do this separately from freeing the table as types can be @@ -39149,6 +39189,8 @@ ecs_table_t *flecs_table_new( flecs_hashmap_result_t table_elem, ecs_table_t *prev) { + ecs_os_perf_trace_push("flecs.table.create"); + ecs_table_t *result = flecs_sparse_add_t(&world->store.tables, ecs_table_t); ecs_assert(result != NULL, ECS_INTERNAL_ERROR, NULL); result->_ = flecs_calloc_t(&world->allocator, ecs_table__t); @@ -39201,6 +39243,8 @@ ecs_table_t *flecs_table_new( ecs_log_pop_2(); + ecs_os_perf_trace_pop("flecs.table.create"); + return result; } @@ -62439,6 +62483,8 @@ ecs_entity_t flecs_run_intern( } } + ecs_os_perf_trace_push(system_data->name); + if (ecs_should_log_3()) { char *path = ecs_get_path(world, system); ecs_dbg_3("worker %d: %s", stage_index, path); @@ -62515,6 +62561,8 @@ ecs_entity_t flecs_run_intern( flecs_defer_end(world, stage); + ecs_os_perf_trace_pop(system_data->name); + return it->interrupted_by; } @@ -62565,6 +62613,9 @@ void flecs_system_fini(ecs_system_t *sys) { sys->run_ctx_free(sys->run_ctx); } + /* Safe cast, type owns name */ + ecs_os_free(ECS_CONST_CAST(char*, sys->name)); + flecs_poly_free(sys, ecs_system_t); } @@ -62663,6 +62714,8 @@ ecs_entity_t ecs_system_init( system->multi_threaded = desc->multi_threaded; system->immediate = desc->immediate; + system->name = ecs_get_path(world, entity); + flecs_system_init_timer(world, entity, desc); if (ecs_get_name(world, entity)) { @@ -66227,6 +66280,8 @@ void flecs_query_cache_rematch_tables( return; } + ecs_os_perf_trace_push("flecs.query.rematch"); + cache->monitor_generation = world->monitor_generation; it = ecs_query_iter(world, cache->query); @@ -66296,6 +66351,8 @@ void flecs_query_cache_rematch_tables( if (world->flags & EcsWorldMeasureFrameTime) { world->info.rematch_time_total += (ecs_ftime_t)ecs_time_measure(&t); } + + ecs_os_perf_trace_pop("flecs.query.rematch"); } /* -- Private API -- */ diff --git a/distr/flecs.h b/distr/flecs.h index be3c77c4ff..8b2ebfa3a4 100644 --- a/distr/flecs.h +++ b/distr/flecs.h @@ -199,6 +199,7 @@ #define FLECS_HTTP /**< Tiny HTTP server for connecting to remote UI */ #define FLECS_REST /**< REST API for querying application data */ // #define FLECS_JOURNAL /**< Journaling addon (disabled by default) */ +// #define FLECS_PERF_TRACE /**< Enable performance tracing (disabled by default) */ #endif // ifndef FLECS_CUSTOM_BUILD /** @def FLECS_LOW_FOOTPRINT @@ -2426,6 +2427,12 @@ typedef char* (*ecs_os_api_module_to_path_t)( const char *module_id); +/* Performance tracing */ +typedef void (*ecs_os_api_perf_trace_t)( + const char *filename, + size_t line, + const char *name); + /* Prefix members of struct with 'ecs_' as some system headers may define * macros for functions like "strdup", "log" or "_free" */ @@ -2502,6 +2509,12 @@ typedef struct ecs_os_api_t { * path that contains module-specif resources or assets */ ecs_os_api_module_to_path_t module_to_etc_; /**< module_to_etc callback. */ + /* Performance tracing */ + ecs_os_api_perf_trace_t perf_trace_push_; + + /* Performance tracing */ + ecs_os_api_perf_trace_t perf_trace_pop_; + int32_t log_level_; /**< Tracing level. */ int32_t log_indent_; /**< Tracing indentation level. */ int32_t log_last_error_; /**< Last logged error code. */ @@ -2812,6 +2825,25 @@ void ecs_os_strset( char **str, const char *value); +/* Profile tracing */ +#ifdef FLECS_PERF_TRACE +#define ecs_os_perf_trace_push(name) ecs_os_perf_trace_push_(__FILE__, __LINE__, name) +#define ecs_os_perf_trace_pop(name) ecs_os_perf_trace_pop_(__FILE__, __LINE__, name) +#else +#define ecs_os_perf_trace_push(name) +#define ecs_os_perf_trace_pop(name) +#endif + +void ecs_os_perf_trace_push_( + const char *file, + size_t line, + const char *name); + +void ecs_os_perf_trace_pop_( + const char *file, + size_t line, + const char *name); + /** Sleep with floating point time. * * @param t The time in seconds. @@ -12117,6 +12149,9 @@ typedef struct ecs_system_t { /** Is system ran in immediate mode */ bool immediate; + /** Cached system name (for perf tracing) */ + const char *name; + /** Userdata for system */ void *ctx; diff --git a/include/flecs.h b/include/flecs.h index 7061e17dac..2b401fff3b 100644 --- a/include/flecs.h +++ b/include/flecs.h @@ -197,6 +197,7 @@ #define FLECS_HTTP /**< Tiny HTTP server for connecting to remote UI */ #define FLECS_REST /**< REST API for querying application data */ // #define FLECS_JOURNAL /**< Journaling addon (disabled by default) */ +// #define FLECS_PERF_TRACE /**< Enable performance tracing (disabled by default) */ #endif // ifndef FLECS_CUSTOM_BUILD /** @def FLECS_LOW_FOOTPRINT diff --git a/include/flecs/addons/system.h b/include/flecs/addons/system.h index c5780cf878..38efec4891 100644 --- a/include/flecs/addons/system.h +++ b/include/flecs/addons/system.h @@ -128,6 +128,9 @@ typedef struct ecs_system_t { /** Is system ran in immediate mode */ bool immediate; + /** Cached system name (for perf tracing) */ + const char *name; + /** Userdata for system */ void *ctx; diff --git a/include/flecs/os_api.h b/include/flecs/os_api.h index ca5ed1cf4d..c6dad4578a 100644 --- a/include/flecs/os_api.h +++ b/include/flecs/os_api.h @@ -240,6 +240,12 @@ typedef char* (*ecs_os_api_module_to_path_t)( const char *module_id); +/* Performance tracing */ +typedef void (*ecs_os_api_perf_trace_t)( + const char *filename, + size_t line, + const char *name); + /* Prefix members of struct with 'ecs_' as some system headers may define * macros for functions like "strdup", "log" or "_free" */ @@ -316,6 +322,12 @@ typedef struct ecs_os_api_t { * path that contains module-specif resources or assets */ ecs_os_api_module_to_path_t module_to_etc_; /**< module_to_etc callback. */ + /* Performance tracing */ + ecs_os_api_perf_trace_t perf_trace_push_; + + /* Performance tracing */ + ecs_os_api_perf_trace_t perf_trace_pop_; + int32_t log_level_; /**< Tracing level. */ int32_t log_indent_; /**< Tracing indentation level. */ int32_t log_last_error_; /**< Last logged error code. */ @@ -626,6 +638,25 @@ void ecs_os_strset( char **str, const char *value); +/* Profile tracing */ +#ifdef FLECS_PERF_TRACE +#define ecs_os_perf_trace_push(name) ecs_os_perf_trace_push_(__FILE__, __LINE__, name) +#define ecs_os_perf_trace_pop(name) ecs_os_perf_trace_pop_(__FILE__, __LINE__, name) +#else +#define ecs_os_perf_trace_push(name) +#define ecs_os_perf_trace_pop(name) +#endif + +void ecs_os_perf_trace_push_( + const char *file, + size_t line, + const char *name); + +void ecs_os_perf_trace_pop_( + const char *file, + size_t line, + const char *name); + /** Sleep with floating point time. * * @param t The time in seconds. diff --git a/src/addons/system/system.c b/src/addons/system/system.c index 5883e35652..896b753a74 100644 --- a/src/addons/system/system.c +++ b/src/addons/system/system.c @@ -59,6 +59,8 @@ ecs_entity_t flecs_run_intern( } } + ecs_os_perf_trace_push(system_data->name); + if (ecs_should_log_3()) { char *path = ecs_get_path(world, system); ecs_dbg_3("worker %d: %s", stage_index, path); @@ -135,6 +137,8 @@ ecs_entity_t flecs_run_intern( flecs_defer_end(world, stage); + ecs_os_perf_trace_pop(system_data->name); + return it->interrupted_by; } @@ -185,6 +189,9 @@ void flecs_system_fini(ecs_system_t *sys) { sys->run_ctx_free(sys->run_ctx); } + /* Safe cast, type owns name */ + ecs_os_free(ECS_CONST_CAST(char*, sys->name)); + flecs_poly_free(sys, ecs_system_t); } @@ -283,6 +290,8 @@ ecs_entity_t ecs_system_init( system->multi_threaded = desc->multi_threaded; system->immediate = desc->immediate; + system->name = ecs_get_path(world, entity); + flecs_system_init_timer(world, entity, desc); if (ecs_get_name(world, entity)) { diff --git a/src/entity.c b/src/entity.c index b56aa711f6..1b2b60deeb 100644 --- a/src/entity.c +++ b/src/entity.c @@ -467,11 +467,13 @@ void flecs_instantiate( ecs_id_record_t *idr = flecs_id_record_get(world, ecs_childof(base)); ecs_table_cache_iter_t it; if (idr && flecs_table_cache_all_iter((ecs_table_cache_t*)idr, &it)) { + ecs_os_perf_trace_push("flecs.instantiate"); const ecs_table_record_t *tr; while ((tr = flecs_table_cache_next(&it, ecs_table_record_t))) { flecs_instantiate_children( world, base, table, row, count, tr->hdr.table); } + ecs_os_perf_trace_pop("flecs.instantiate"); } } @@ -895,6 +897,8 @@ void flecs_commit( return; } + ecs_os_perf_trace_push("flecs.commit"); + if (src_table) { ecs_assert(dst_table != NULL, ECS_INTERNAL_ERROR, NULL); flecs_table_traversable_add(dst_table, is_trav); @@ -930,7 +934,9 @@ void flecs_commit( ECS_OUT_OF_RANGE, 0); ecs_check(entity >= world->info.min_id, ECS_OUT_OF_RANGE, 0); - } + } + + ecs_os_perf_trace_pop("flecs.commit"); error: flecs_journal_end(); @@ -2757,6 +2763,8 @@ void ecs_delete( return; } + ecs_os_perf_trace_push("flecs.delete"); + ecs_record_t *r = flecs_entities_try(world, entity); if (r) { flecs_journal_begin(world, EcsJournalDelete, entity, NULL, NULL); @@ -2805,6 +2813,7 @@ void ecs_delete( flecs_defer_end(world, stage); error: + ecs_os_perf_trace_pop("flecs.delete"); return; } @@ -4976,6 +4985,8 @@ bool flecs_defer_end( ecs_assert(stage->defer > 0, ECS_INTERNAL_ERROR, NULL); if (!--stage->defer) { + ecs_os_perf_trace_push("flecs.commands.merge"); + /* Test whether we're flushing to another queue or whether we're * flushing to the storage */ bool merge_to_world = false; @@ -5170,6 +5181,8 @@ bool flecs_defer_end( } } + ecs_os_perf_trace_pop("flecs.commands.merge"); + return true; } diff --git a/src/observable.c b/src/observable.c index 5143638b32..99bbbbebd1 100644 --- a/src/observable.c +++ b/src/observable.c @@ -1105,6 +1105,8 @@ void flecs_emit( ecs_check(desc->table != NULL, ECS_INVALID_PARAMETER, NULL); ecs_check(desc->observable != NULL, ECS_INVALID_PARAMETER, NULL); + ecs_os_perf_trace_push("flecs.emit"); + ecs_time_t t = {0}; bool measure_time = world->flags & EcsWorldMeasureSystemTime; if (measure_time) { @@ -1429,6 +1431,8 @@ void flecs_emit( error: world->stages[0]->defer = defer; + ecs_os_perf_trace_pop("flecs.emit"); + if (measure_time) { world->info.emit_time_total += (ecs_ftime_t)ecs_time_measure(&t); } diff --git a/src/os_api.c b/src/os_api.c index ccd801b4b0..627021587b 100644 --- a/src/os_api.c +++ b/src/os_api.c @@ -350,6 +350,26 @@ void ecs_os_strset(char **str, const char *value) { ecs_os_free(old); } +void ecs_os_perf_trace_push_( + const char *file, + size_t line, + const char *name) +{ + if (ecs_os_api.perf_trace_push_) { + ecs_os_api.perf_trace_push_(file, line, name); + } +} + +void ecs_os_perf_trace_pop_( + const char *file, + size_t line, + const char *name) +{ + if (ecs_os_api.perf_trace_pop_) { + ecs_os_api.perf_trace_pop_(file, line, name); + } +} + /* Replace dots with underscores */ static char *module_file_base(const char *module, char sep) { diff --git a/src/query/engine/cache.c b/src/query/engine/cache.c index 187becd33f..308c04330b 100644 --- a/src/query/engine/cache.c +++ b/src/query/engine/cache.c @@ -854,6 +854,8 @@ void flecs_query_cache_rematch_tables( return; } + ecs_os_perf_trace_push("flecs.query.rematch"); + cache->monitor_generation = world->monitor_generation; it = ecs_query_iter(world, cache->query); @@ -923,6 +925,8 @@ void flecs_query_cache_rematch_tables( if (world->flags & EcsWorldMeasureFrameTime) { world->info.rematch_time_total += (ecs_ftime_t)ecs_time_measure(&t); } + + ecs_os_perf_trace_pop("flecs.query.rematch"); } /* -- Private API -- */ diff --git a/src/storage/table.c b/src/storage/table.c index 36ae0a0e66..2322ff0190 100644 --- a/src/storage/table.c +++ b/src/storage/table.c @@ -987,6 +987,8 @@ void flecs_table_fini( ECS_INTERNAL_ERROR, NULL); (void)world; + ecs_os_perf_trace_push("flecs.table.free"); + if (!is_root && !(world->flags & EcsWorldQuit)) { if (table->flags & EcsTableHasOnTableDelete) { flecs_table_emit(world, table, EcsOnTableDelete); @@ -1037,6 +1039,8 @@ void flecs_table_fini( } ecs_log_pop_2(); + + ecs_os_perf_trace_pop("flecs.table.free"); } /* Free table type. Do this separately from freeing the table as types can be diff --git a/src/storage/table_graph.c b/src/storage/table_graph.c index 11b87ea7ea..1796add3c0 100644 --- a/src/storage/table_graph.c +++ b/src/storage/table_graph.c @@ -545,6 +545,8 @@ ecs_table_t *flecs_table_new( flecs_hashmap_result_t table_elem, ecs_table_t *prev) { + ecs_os_perf_trace_push("flecs.table.create"); + ecs_table_t *result = flecs_sparse_add_t(&world->store.tables, ecs_table_t); ecs_assert(result != NULL, ECS_INTERNAL_ERROR, NULL); result->_ = flecs_calloc_t(&world->allocator, ecs_table__t); @@ -597,6 +599,8 @@ ecs_table_t *flecs_table_new( ecs_log_pop_2(); + ecs_os_perf_trace_pop("flecs.table.create"); + return result; } diff --git a/src/world.c b/src/world.c index 82f0a8ee69..39a7c62c69 100644 --- a/src/world.c +++ b/src/world.c @@ -454,6 +454,8 @@ void flecs_eval_component_monitor( return; } + ecs_os_perf_trace_push("flecs.component_monitor.eval"); + world->monitors.is_dirty = false; ecs_map_iter_t it = ecs_map_iter(&world->monitors.monitors); @@ -475,6 +477,8 @@ void flecs_eval_component_monitor( }); } } + + ecs_os_perf_trace_pop("flecs.component_monitor.eval"); } void flecs_monitor_mark_dirty( @@ -2012,6 +2016,8 @@ void flecs_process_pending_tables( return; } + ecs_os_perf_trace_push("flecs.process_pending_tables"); + flecs_journal_begin(world, EcsJournalTableEvents, 0, 0, 0); do { @@ -2066,6 +2072,8 @@ void flecs_process_pending_tables( } while ((count = flecs_sparse_count(world->pending_tables))); flecs_journal_end(); + + ecs_os_perf_trace_pop("flecs.process_pending_tables"); } void flecs_table_set_empty( @@ -2125,11 +2133,13 @@ int32_t ecs_delete_empty_tables( { flecs_poly_assert(world, ecs_world_t); + ecs_os_perf_trace_push("flecs.delete_empty_tables"); + /* Make sure empty tables are in the empty table lists */ ecs_run_aperiodic(world, EcsAperiodicEmptyTables); ecs_time_t start = {0}, cur = {0}; - int32_t delete_count = 0, clear_count = 0; + int32_t delete_count = 0; bool time_budget = false; if (ECS_NEQZERO(time_budget_seconds) || (ecs_should_log_1() && ecs_os_has_time())) { @@ -2168,24 +2178,13 @@ int32_t ecs_delete_empty_tables( flecs_table_fini(world, table); delete_count ++; } else if (clear_generation && (gen > clear_generation)) { - if (flecs_table_shrink(world, table)) { - clear_count ++; - } + flecs_table_shrink(world, table); } } } done: - if (ecs_should_log_1() && ecs_os_has_time()) { - if (delete_count) { - ecs_dbg_1("#[red]deleted#[normal] %d empty tables in %.2fs", - delete_count, ecs_time_measure(&start)); - } - if (clear_count) { - ecs_dbg_1("#[red]cleared#[normal] %d empty tables in %.2fs", - clear_count, ecs_time_measure(&start)); - } - } + ecs_os_perf_trace_pop("flecs.delete_empty_tables"); return delete_count; } diff --git a/test/custom_builds/c/perf_trace/include/perf_trace.h b/test/custom_builds/c/perf_trace/include/perf_trace.h new file mode 100644 index 0000000000..e40d32c4cd --- /dev/null +++ b/test/custom_builds/c/perf_trace/include/perf_trace.h @@ -0,0 +1,16 @@ +#ifndef PERF_TRACE_H +#define PERF_TRACE_H + +/* This generated file contains includes for project dependencies */ +#include "perf_trace/bake_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/test/custom_builds/c/perf_trace/include/perf_trace/bake_config.h b/test/custom_builds/c/perf_trace/include/perf_trace/bake_config.h new file mode 100644 index 0000000000..1371e08991 --- /dev/null +++ b/test/custom_builds/c/perf_trace/include/perf_trace/bake_config.h @@ -0,0 +1,24 @@ +/* + ) + (.) + .|. + | | + _.--| |--._ + .-'; ;`-'& ; `&. + \ & ; & &_/ + |"""---...---"""| + \ | | | | | | | / + `---.|.|.|.---' + + * This file is generated by bake.lang.c for your convenience. Headers of + * dependencies will automatically show up in this file. Include bake_config.h + * in your main project file. Do not edit! */ + +#ifndef PERF_TRACE_BAKE_CONFIG_H +#define PERF_TRACE_BAKE_CONFIG_H + +/* Headers of public dependencies */ +#include "../../deps/flecs.h" + +#endif + diff --git a/test/custom_builds/c/perf_trace/project.json b/test/custom_builds/c/perf_trace/project.json new file mode 100644 index 0000000000..f347f850fe --- /dev/null +++ b/test/custom_builds/c/perf_trace/project.json @@ -0,0 +1,14 @@ +{ + "id": "perf_trace", + "type": "application", + "value": { + "public": false, + "use": [ + "flecs" + ], + "standalone": true + }, + "lang.c": { + "defines": ["FLECS_PERF_TRACE"] + } +} diff --git a/test/custom_builds/c/perf_trace/src/main.c b/test/custom_builds/c/perf_trace/src/main.c new file mode 100644 index 0000000000..0a62999cfc --- /dev/null +++ b/test/custom_builds/c/perf_trace/src/main.c @@ -0,0 +1,40 @@ +#include +#include + +int push_invoked = 0; +int pop_invoked = 0; + +static +void trace_push(const char *file, size_t line, const char *name) { + (void)file; + (void)line; + (void)name; + push_invoked ++; +} + +static +void trace_pop(const char *file, size_t line, const char *name) { + (void)file; + (void)line; + (void)name; + pop_invoked ++; +} + +int main(int argc, char *argv[]) { + ecs_os_set_api_defaults(); + ecs_os_api_t os_api = ecs_os_get_api(); + os_api.perf_trace_push_ = trace_push; + os_api.perf_trace_pop_ = trace_pop; + ecs_os_set_api(&os_api); + + ecs_world_t *world = ecs_init_w_args(argc, argv); + + /* Run systems */ + ecs_progress(world, 0); + + assert(push_invoked != 0); + assert(pop_invoked != 0); + assert(push_invoked == pop_invoked); + + return ecs_fini(world); +}