Skip to content

Commit

Permalink
Add performance tracing hooks to Flecs (#1326)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #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
  • Loading branch information
SanderMertens committed Aug 29, 2024
1 parent 6cb8291 commit f9ac2aa
Show file tree
Hide file tree
Showing 17 changed files with 308 additions and 30 deletions.
87 changes: 72 additions & 15 deletions distr/flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -7768,6 +7776,7 @@ void ecs_delete(

flecs_defer_end(world, stage);
error:
ecs_os_perf_trace_pop("flecs.delete");
return;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -10133,6 +10144,8 @@ bool flecs_defer_end(
}
}

ecs_os_perf_trace_pop("flecs.commands.merge");

return true;
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -17822,6 +17861,8 @@ void flecs_eval_component_monitor(
});
}
}

ecs_os_perf_trace_pop("flecs.component_monitor.eval");
}

void flecs_monitor_mark_dirty(
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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())) {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -39201,6 +39243,8 @@ ecs_table_t *flecs_table_new(

ecs_log_pop_2();

ecs_os_perf_trace_pop("flecs.table.create");

return result;
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 -- */
Expand Down
35 changes: 35 additions & 0 deletions distr/flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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" */

Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;

Expand Down
1 change: 1 addition & 0 deletions include/flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions include/flecs/addons/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Loading

0 comments on commit f9ac2aa

Please sign in to comment.