Skip to content

Commit

Permalink
#88 finish new stats API, remove old one
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed Oct 31, 2019
1 parent 1de1a1c commit 539b9ae
Show file tree
Hide file tree
Showing 12 changed files with 605 additions and 644 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ Additionally, applications can define entities with the `ECS_ENTITY` macro, whic
ECS_ENTITY(world, MyEntity, Point);
```
Components, systems, tasks, families and prefabs automatically register the `EcsId` component when they are created, and can thus be looked up with `ecs_lookup`.
Components, systems, tasks, types and prefabs automatically register the `EcsId` component when they are created, and can thus be looked up with `ecs_lookup`.
### Task
A task is a system that has no interest expression. Tasks are run once every frame. Tasks are defined the same way as normal systems, but instead of an interest expression, you specify `0`:
Expand Down
8 changes: 4 additions & 4 deletions include/flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ typedef void (*ecs_module_init_action_t)(
#define EEcsOnDemand (11)

/* World entity */
#define EcsWorld (12)
#define EcsWorld (13)

/* Singleton entity */
#define EcsSingleton (ECS_SINGLETON)
Expand Down Expand Up @@ -1173,7 +1173,7 @@ ecs_entity_t _ecs_set_singleton_ptr(

/** Check if entity has the specified type.
* This operation checks if the entity has the components associated with the
* specified type. It accepts component handles, families and prefabs.
* specified type. It accepts component handles, types and prefabs.
*
* For example, if an entity has component 'Foo' and a type has 'Foo, Bar'
* invoking this function with the entity and type as type will return false
Expand Down Expand Up @@ -1208,7 +1208,7 @@ bool _ecs_has_owned(

/** Check if entity has any of the components in the specified type.
* This operation checks if the entity has any of the components associated with
* the specified type. It accepts component handles, families and prefabs.
* the specified type. It accepts component handles, types and prefabs.
*
* For example, if an entity has component 'Foo' and a type has 'Foo, Bar'
* invoking this function with the entity and type as type will return true
Expand Down Expand Up @@ -2060,7 +2060,7 @@ ecs_entity_t ecs_new_type(
*
* Entities can override components from a prefab by adding the component with
* ecs_add. When a component is overridden, its value will be copied from the
* prefab. This technique can be combined with families to automatically
* prefab. This technique can be combined with types to automatically
* initialize entities, like this:
*
* ECS_PREFAB(world, MyPrefab, Foo);
Expand Down
6 changes: 6 additions & 0 deletions include/flecs/util/os_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
extern "C" {
#endif

/* Allocation counters (not thread safe) */
extern uint64_t ecs_os_api_malloc_count;
extern uint64_t ecs_os_api_realloc_count;
extern uint64_t ecs_os_api_calloc_count;
extern uint64_t ecs_os_api_free_count;

/* Use handle types that _at least_ can store pointers */
typedef uintptr_t ecs_os_thread_t;
typedef uintptr_t ecs_os_cond_t;
Expand Down
182 changes: 95 additions & 87 deletions include/flecs/util/stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,54 +5,103 @@
extern "C" {
#endif

/* Type to keep track of memory that is in use vs. allocated */
typedef struct ecs_memory_stat_t {
uint32_t allocd;
uint32_t used;
} ecs_memory_stat_t;

/* Global statistics on memory allocations */
typedef struct EcsAllocStats {
uint64_t malloc_count;
uint64_t realloc_count;
uint64_t calloc_count;
uint64_t free_count;
} EcsAllocStats;

/* Memory statistics on row (reactive) systems */
typedef struct EcsRowSystemMemoryStats {
uint32_t base;
ecs_memory_stat_t columns;
ecs_memory_stat_t components;
} EcsRowSystemMemoryStats;

/* Memory statistics on column (periodic) systems */
typedef struct EcsColSystemMemoryStats {
uint32_t base;
ecs_memory_stat_t columns;
ecs_memory_stat_t active_tables;
ecs_memory_stat_t inactive_tables;
ecs_memory_stat_t jobs;
uint32_t other;
} EcsColSystemMemoryStats;

/* Memory statistics for a world */
typedef struct EcsMemoryStats {
ecs_memory_stat_t total;
ecs_memory_stat_t entities;
ecs_memory_stat_t components;
ecs_memory_stat_t systems;
ecs_memory_stat_t types;
ecs_memory_stat_t tables;
ecs_memory_stat_t stage;
ecs_memory_stat_t world;
} EcsMemoryStats;

/* Component statistics */
typedef struct EcsComponentStats {
ecs_entity_t handle;
const char *id;
uint16_t size;
uint32_t memory_used;
uint32_t memory_allocd;
uint32_t entities;
uint32_t tables;
} EcsComponentStats;

/* System statistics */
typedef struct EcsSystemStats {
ecs_entity_t handle;
const char *id;
const char *signature;
EcsSystemKind kind;
uint32_t tables_matched;
uint32_t entities_matched;
uint64_t invoke_count;
float period;
float time_spent;
bool enabled;
bool active;
bool is_hidden;
} EcsSystemStats;

typedef struct EcsFeatureStats {
/* Type statistics (only for named types, created with ECS_TYPE) */
typedef struct EcsTypeStats {
const char *id;
char *entities;
uint32_t system_count;
uint32_t systems_enabled;
ecs_type_t type;
ecs_type_t normalized_type;
uint32_t entity_count;
uint32_t entity_childof_count;
uint32_t entity_instanceof_count;
uint32_t component_count;
uint32_t col_system_count;
uint32_t row_system_count;
uint32_t enabled_system_count;
uint32_t active_system_count;
bool is_hidden;
} EcsFeatureStats;

typedef struct EcsComponentStats {
ecs_entity_t handle;
const char *id;
uint16_t size;
uint32_t memory_used;
uint32_t memory_allocd;
uint32_t entities;
uint32_t tables;
} EcsComponentStats;

typedef struct EcsMemoryStat {
uint32_t allocd;
uint32_t used;
} EcsMemoryStat;
} EcsTypeStats;

typedef struct EcsMemoryStats {
EcsMemoryStat total;
EcsMemoryStat components;
EcsMemoryStat entities;
EcsMemoryStat systems;
EcsMemoryStat families;
EcsMemoryStat tables;
EcsMemoryStat stage;
EcsMemoryStat world;
} EcsMemoryStats;
/* Table statistics */
typedef struct EcsTableStats {
ecs_type_t type;
uint32_t column_count;
uint32_t entity_count;
uint32_t systems_matched;
ecs_memory_stat_t data_memory;
uint32_t other_memory;
} EcsTableStats;

/* World statistics */
typedef struct EcsWorldStats {
uint32_t table_count;
uint32_t component_count;
Expand All @@ -66,76 +115,35 @@ typedef struct EcsWorldStats {
double target_fps;
} EcsWorldStats;

typedef struct ecs_world_stats_t {
uint32_t system_count;
uint32_t table_count;
uint32_t component_count;
uint32_t entity_count;
uint32_t thread_count;
uint32_t tick_count;
float system_time;
float frame_time;
float merge_time;
EcsMemoryStats memory;
ecs_vector_t *features;
ecs_vector_t *on_load_systems;
ecs_vector_t *post_load_systems;
ecs_vector_t *pre_update_systems;
ecs_vector_t *on_update_systems;
ecs_vector_t *on_validate_systems;
ecs_vector_t *post_update_systems;
ecs_vector_t *pre_store_systems;
ecs_vector_t *on_store_systems;
ecs_vector_t *task_systems;
ecs_vector_t *inactive_systems;
ecs_vector_t *manual_systems;
ecs_vector_t *on_add_systems;
ecs_vector_t *on_remove_systems;
ecs_vector_t *on_set_systems;
ecs_vector_t *components;
bool frame_profiling;
bool system_profiling;
} ecs_world_stats_t;

FLECS_EXPORT
void ecs_get_stats(
ecs_world_t *world,
ecs_world_stats_t *stats);

FLECS_EXPORT
void ecs_free_stats(
ecs_world_stats_t *stats);

FLECS_EXPORT
void ecs_measure_frame_time(
ecs_world_t *world,
bool enable);

FLECS_EXPORT
void ecs_measure_system_time(
ecs_world_t *world,
bool enable);


/* Stats module component */
typedef struct FlecsStats {
ECS_DECLARE_COMPONENT(EcsAllocStats);
ECS_DECLARE_COMPONENT(EcsWorldStats);
ECS_DECLARE_COMPONENT(EcsMemoryStats);
ECS_DECLARE_COMPONENT(EcsSystemStats);
ECS_DECLARE_COMPONENT(EcsFeatureStats);
ECS_DECLARE_COMPONENT(EcsColSystemMemoryStats);
ECS_DECLARE_COMPONENT(EcsRowSystemMemoryStats);
ECS_DECLARE_COMPONENT(EcsComponentStats);
ECS_DECLARE_COMPONENT(EcsMemoryStats);
ECS_DECLARE_COMPONENT(EcsWorldStats);
ECS_DECLARE_COMPONENT(EcsTableStats);
ECS_DECLARE_COMPONENT(EcsTablePtr);
ECS_DECLARE_COMPONENT(EcsTypeStats);
} FlecsStats;

void FlecsStatsImport(
ecs_world_t *world,
int flags);

#define FlecsStatsImportHandles(handles)\
ECS_IMPORT_COMPONENT(handles, EcsAllocStats);\
ECS_IMPORT_COMPONENT(handles, EcsWorldStats);\
ECS_IMPORT_COMPONENT(handles, EcsMemoryStats);\
ECS_IMPORT_COMPONENT(handles, EcsSystemStats);\
ECS_IMPORT_COMPONENT(handles, EcsFeatureStats);\
ECS_IMPORT_COMPONENT(handles, EcsColSystemMemoryStats);\
ECS_IMPORT_COMPONENT(handles, EcsRowSystemMemoryStats);\
ECS_IMPORT_COMPONENT(handles, EcsComponentStats);\
ECS_IMPORT_COMPONENT(handles, EcsMemoryStats);\
ECS_IMPORT_COMPONENT(handles, EcsWorldStats);
ECS_IMPORT_COMPONENT(handles, EcsTableStats);\
ECS_IMPORT_COMPONENT(handles, EcsTablePtr);\
ECS_IMPORT_COMPONENT(handles, EcsTypeStats);

#ifdef __cplusplus
}
Expand Down
3 changes: 3 additions & 0 deletions src/column_system.c
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,7 @@ ecs_entity_t ecs_new_col_system(
system_data->base.signature = strdup(sig);
system_data->base.time_spent = 0;
system_data->base.columns = ecs_vector_new(&system_column_params, count);
system_data->base.invoke_count = 0;
system_data->base.kind = kind;
system_data->base.cascade_by = 0;
system_data->base.has_refs = false;
Expand Down Expand Up @@ -999,6 +1000,8 @@ ecs_entity_t _ecs_run_w_filter(
if (measure_time) {
system_data->base.time_spent += ecs_time_measure(&time_start);
}

system_data->base.invoke_count ++;

return interrupted_by;
}
Expand Down
10 changes: 9 additions & 1 deletion src/flecs_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ ecs_type_t ecs_type_find_intern(
ecs_entity_t *buf,
uint32_t count);

/* Merge add/remove families */
/* Merge add/remove types */
ecs_type_t ecs_type_merge_intern(
ecs_world_t *world,
ecs_stage_t *stage,
Expand Down Expand Up @@ -378,6 +378,14 @@ void ecs_revalidate_system_refs(
ecs_world_t *world,
ecs_entity_t system);

void ecs_measure_frame_time(
ecs_world_t *world,
bool enable);

void ecs_measure_system_time(
ecs_world_t *world,
bool enable);

/* -- Worker API -- */

/* Compute schedule based on current number of entities matching system */
Expand Down
44 changes: 40 additions & 4 deletions src/os_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ static bool ecs_os_api_debug_enabled = false;

ecs_os_api_t ecs_os_api;

uint64_t ecs_os_api_malloc_count = 0;
uint64_t ecs_os_api_realloc_count = 0;
uint64_t ecs_os_api_calloc_count = 0;
uint64_t ecs_os_api_free_count = 0;

void ecs_os_set_api(
ecs_os_api_t *os_api)
{
Expand Down Expand Up @@ -227,6 +232,37 @@ void ecs_os_gettime(ecs_time_t *timeOut)
timeOut->nanosec = now - timeOut->sec * 1000000000;
}

static
void* ecs_os_api_malloc(size_t size) {
ecs_os_api_malloc_count ++;
return malloc(size);
}

static
void* ecs_os_api_calloc(size_t num, size_t size) {
ecs_os_api_calloc_count ++;
return calloc(num, size);
}

static
void* ecs_os_api_realloc(void *ptr, size_t size) {
if (ptr) {
ecs_os_api_realloc_count ++;
} else {
/* If not actually reallocing, treat as malloc */
ecs_os_api_malloc_count ++;
}
return realloc(ptr, size);
}

static
void ecs_os_api_free(void *ptr) {
if (ptr) {
ecs_os_api_free_count ++;
}
free(ptr);
}

void ecs_os_set_api_defaults(void)
{
/* Don't overwrite if already initialized */
Expand All @@ -236,10 +272,10 @@ void ecs_os_set_api_defaults(void)

ecs_os_time_setup();

ecs_os_api.malloc = malloc;
ecs_os_api.free = free;
ecs_os_api.realloc = realloc;
ecs_os_api.calloc = calloc;
ecs_os_api.malloc = ecs_os_api_malloc;
ecs_os_api.free = ecs_os_api_free;
ecs_os_api.realloc = ecs_os_api_realloc;
ecs_os_api.calloc = ecs_os_api_calloc;

#ifdef __BAKE__
ecs_os_api.thread_new = bake_thread_new;
Expand Down
2 changes: 1 addition & 1 deletion src/stage.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ void ecs_stage_merge(
/* Keep track of old number of tables so we know how many have been added */
uint32_t old_table_count = ecs_chunked_count(world->main_stage.tables);

/* Merge any new families */
/* Merge any new types */
merge_families(world, stage);

/* Merge entities. This can create tables if a new combination of components
Expand Down
Loading

0 comments on commit 539b9ae

Please sign in to comment.