diff --git a/src/app.c b/src/app.c index 6837042b..da4e173b 100644 --- a/src/app.c +++ b/src/app.c @@ -33,8 +33,6 @@ struct exit_callback { struct sys_thread thread; }; -struct app_statistics _g_app_statistics = ZI; - GLOBAL struct { struct arena arena; struct string write_path; diff --git a/src/app.h b/src/app.h index e85439f6..807ffa7c 100644 --- a/src/app.h +++ b/src/app.h @@ -4,20 +4,6 @@ #define APP_EXIT_CALLBACK_FUNC_DEF(name) void name(void) typedef APP_EXIT_CALLBACK_FUNC_DEF(app_exit_callback_func); -struct app_statistics { - struct atomic_u64 sock_bytes_sent; - struct atomic_u64 sock_bytes_received; - struct atomic_u64 memory_committed; - struct atomic_u64 memory_reserved; - struct atomic_u64 num_arenas; -}; - -INLINE struct app_statistics *app_statistics(void) -{ - extern struct app_statistics _g_app_statistics; - return &_g_app_statistics; -} - struct string app_write_path_cat(struct arena *arena, struct string filename); /* Register a function that will be called when the application exits */ diff --git a/src/arena.c b/src/arena.c index 0919c432..a54f0724 100644 --- a/src/arena.c +++ b/src/arena.c @@ -3,7 +3,7 @@ #include "memory.h" #include "string.h" #include "atomic.h" -#include "app.h" +#include "gstat.h" /* Arbitrary block size */ #define ARENA_BLOCK_SIZE 4096 @@ -27,7 +27,7 @@ struct arena arena_alloc(u64 reserve) sys_panic(LIT("Failed to reserve memory")); } arena.reserved = reserve; - atomic_u64_eval_add_u64(&app_statistics()->memory_reserved, arena.reserved); + gstat_add(GSTAT_MEMORY_RESERVED, arena.reserved); /* Commit one block to start with */ arena.base = sys_memory_commit(arena.base, ARENA_BLOCK_SIZE); @@ -36,14 +36,14 @@ struct arena arena_alloc(u64 reserve) sys_panic(LIT("Failed to commit initial memory block: System may be out of memory")); } arena.committed = ARENA_BLOCK_SIZE; - atomic_u64_eval_add_u64(&app_statistics()->memory_committed, arena.committed); + gstat_add(GSTAT_MEMORY_COMMITTED, arena.committed); __profalloc(arena.base, ARENA_BLOCK_SIZE); ASAN_POISON(arena.base, ARENA_BLOCK_SIZE); /* Arena should be 64k aligned */ ASSERT(((u64)arena.base & 0xFFFF) == 0); - atomic_u64_inc_eval(&app_statistics()->num_arenas); + gstat_add(GSTAT_NUM_ARENAS, 1); return arena; } @@ -53,9 +53,9 @@ void arena_release(struct arena *arena) ASAN_UNPOISON(arena->base, arena->committed); __prof; __proffree(arena->base); - atomic_u64_eval_add_i64(&app_statistics()->memory_committed, -((i64)arena->committed)); - atomic_u64_eval_add_i64(&app_statistics()->memory_reserved, -((i64)arena->reserved)); - atomic_u64_dec_eval(&app_statistics()->num_arenas); + gstat_sub(GSTAT_MEMORY_COMMITTED, arena->committed); + gstat_sub(GSTAT_MEMORY_RESERVED, arena->reserved); + gstat_sub(GSTAT_NUM_ARENAS, 1); sys_memory_release(arena->base); } @@ -89,7 +89,7 @@ void *arena_push_bytes(struct arena *arena, u64 size, u64 align) sys_panic(LIT("Failed to commit new memory block: System may be out of memory")); } arena->committed += commit_bytes; - atomic_u64_eval_add_u64(&app_statistics()->memory_committed, commit_bytes); + gstat_add(GSTAT_MEMORY_COMMITTED, commit_bytes); __proffree(arena->base); __profalloc(arena->base, arena->committed + commit_bytes); ASAN_POISON(commit_address, commit_bytes); @@ -124,7 +124,7 @@ void arena_decommit_unused_blocks(struct arena *arena) u64 decommit_size = (arena->base + arena->committed) - decommit_start; sys_memory_decommit(decommit_start, decommit_size); arena->committed = next_block_pos; - atomic_u64_eval_add_i64(&app_statistics()->memory_committed, -((i64)decommit_size)); + gstat_sub(GSTAT_MEMORY_COMMITTED, decommit_size); } } diff --git a/src/config.h b/src/config.h index d59b20fd..4e23dacb 100644 --- a/src/config.h +++ b/src/config.h @@ -63,6 +63,9 @@ #define BITBUFF_DEBUG 0 #define BITBUFF_TEST RTC +/* If enabled, things like network writes & memory allocations will be tracked in a global statistics struct */ +#define GSTAT_ENABLED 1 + /* ========================== * * Settings * ========================== */ diff --git a/src/gstat.c b/src/gstat.c new file mode 100644 index 00000000..6cb0199e --- /dev/null +++ b/src/gstat.c @@ -0,0 +1,5 @@ +#include "gstat.h" + +#if GSTAT_ENABLED +struct _gstats _g_gstats = ZI; +#endif diff --git a/src/gstat.h b/src/gstat.h new file mode 100644 index 00000000..2f5a9fe1 --- /dev/null +++ b/src/gstat.h @@ -0,0 +1,33 @@ +#ifndef GSTAT_H +#define GSTAT_H + +/* Program-wide statistics */ + +#if GSTAT_ENABLED + +#include "atomic.h" + +struct _gstats { + struct atomic_u64 GSTAT_SOCK_BYTES_SENT; + struct atomic_u64 GSTAT_SOCK_BYTES_RECEIVED; + struct atomic_u64 GSTAT_MEMORY_COMMITTED; + struct atomic_u64 GSTAT_MEMORY_RESERVED; + struct atomic_u64 GSTAT_NUM_ARENAS; +}; + +extern struct _gstats _g_gstats; + +#define gstat_add(name, v) atomic_u64_eval_add_u64(&_g_gstats.name, (v)) +#define gstat_sub(name, v) atomic_u64_eval_add_i64(&_g_gstats.name, -((i64)(v))) +#define gstat_get(name) atomic_u64_eval(&_g_gstats.name) + +#else + +#define gstat_add(name, v) +#define gstat_sub(name, v) +#define gstat_get(name) 0 + +#endif + + +#endif diff --git a/src/sim_ent.c b/src/sim_ent.c index 9f798b23..997cb801 100644 --- a/src/sim_ent.c +++ b/src/sim_ent.c @@ -117,6 +117,33 @@ void sim_ent_release(struct sim_ent *ent) sim_ent_release_raw(ent); } +void sim_ent_release_all_with_prop(struct sim_snapshot *ss, enum sim_ent_prop prop) +{ + struct temp_arena scratch = scratch_begin_no_conflict(); + + struct sim_ent **ents_to_release = arena_dry_push(scratch.arena, struct sim_ent *); + u64 ents_to_release_count = 0; + for (u64 ent_index = 0; ent_index < ss->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ss->ents[ent_index]; + if (ent->valid && sim_ent_has_prop(ent, prop)) { + *arena_push(scratch.arena, struct sim_ent *) = ent; + ++ents_to_release_count; + } + } + + /* Release from snapshot */ + /* TODO: Breadth first iteration to only release parent entities (since + * child entities will be released along with parent anyway) */ + for (u64 i = 0; i < ents_to_release_count; ++i) { + struct sim_ent *ent = ents_to_release[i]; + if (ent->is_top && !ent->is_root) { + sim_ent_release(ent); + } + } + + scratch_end(scratch); +} + /* ========================== * * Activate * ========================== */ diff --git a/src/sim_ent.h b/src/sim_ent.h index 4db0ac05..81c708e6 100644 --- a/src/sim_ent.h +++ b/src/sim_ent.h @@ -400,6 +400,7 @@ struct sim_ent *sim_ent_alloc_sync_dst(struct sim_ent *parent, struct sim_client void sim_ent_release_raw(struct sim_ent *ent); void sim_ent_release(struct sim_ent *ent); +void sim_ent_release_all_with_prop(struct sim_snapshot *ss, enum sim_ent_prop prop); /* Activate */ void sim_ent_activate(struct sim_ent *ent, u64 current_tick); diff --git a/src/sim_step.c b/src/sim_step.c index 42ce92b7..4650f62c 100644 --- a/src/sim_step.c +++ b/src/sim_step.c @@ -16,114 +16,6 @@ #include "bitbuff.h" #include "host.h" -/* ========================== * - * Ent lookup - * ========================== */ - -struct sim_lookup sim_lookup_alloc(u64 num_buckets) -{ - ASSERT(num_buckets > 0); - struct sim_lookup l = ZI; - l.arena = arena_alloc(GIGABYTE(64)); - l.num_buckets = num_buckets; - sim_lookup_reset(&l); - return l; -} - -void sim_lookup_release(struct sim_lookup *l) -{ - arena_release(&l->arena); -} - -void sim_lookup_reset(struct sim_lookup *l) -{ - arena_reset(&l->arena); - l->buckets = arena_push_array_zero(&l->arena, struct sim_lookup_bucket, l->num_buckets); - l->first_free_entry = NULL; -} - -struct sim_lookup_entry *sim_lookup_get(struct sim_lookup *l, struct sim_lookup_key key) -{ - u64 index = key.hash % l->num_buckets; - struct sim_lookup_bucket *bucket = &l->buckets[index]; - struct sim_lookup_entry *res = NULL; - for (struct sim_lookup_entry *e = bucket->first; e; e = e->next) { - if (e->key.hash == key.hash) { - res = e; - break; - } - } - return res; -} - -void sim_lookup_set(struct sim_lookup *l, struct sim_lookup_key key, struct sim_ent_handle handle) -{ - u64 index = key.hash % l->num_buckets; - struct sim_lookup_bucket *bucket = &l->buckets[index]; - - struct sim_lookup_entry *prev = NULL; - struct sim_lookup_entry **slot = &bucket->first; - while (*slot) { - if ((*slot)->key.hash == key.hash) { - break; - } - prev = *slot; - slot = &(*slot)->next; - } - - struct sim_lookup_entry *entry = *slot; - if (entry) { - /* Set existing entry */ - entry->ent = handle; - } else { - /* Allocate entry */ - if (l->first_free_entry) { - entry = l->first_free_entry; - l->first_free_entry->prev = NULL; - l->first_free_entry = entry->next; - } else { - entry = arena_push(&l->arena, struct sim_lookup_entry); - } - MEMZERO_STRUCT(entry); - - entry->key = key; - entry->ent = handle; - if (prev) { - entry->prev = prev; - prev->next = entry; - } - - bucket->last = entry; - *slot = entry; - } -} - -void sim_lookup_remove(struct sim_lookup *l, struct sim_lookup_entry *entry) -{ - struct sim_lookup_bucket *bucket = &l->buckets[entry->key.hash % l->num_buckets]; - struct sim_lookup_entry *prev = entry->prev; - struct sim_lookup_entry *next = entry->next; - - if (prev) { - prev->next = next; - } else { - bucket->first = next; - } - - if (next) { - next->prev = prev; - } else { - bucket->last = prev; - } - - if (l->first_free_entry) { - l->first_free_entry->prev = entry; - } - entry->next = l->first_free_entry; - entry->prev = NULL; - l->first_free_entry = entry; -} - /* ========================== * * Sim accel * ========================== */ @@ -140,10 +32,8 @@ void sim_accel_release(struct sim_accel *accel) space_release(accel->space); } -void sim_accel_rebuild(struct sim_snapshot *ss, struct sim_accel *accel) +void sim_accel_reset(struct sim_snapshot *ss, struct sim_accel *accel) { - /* FIXME: Rebuild collision debug lookup */ - space_reset(accel->space); /* Reset ent space handles */ @@ -153,8 +43,6 @@ void sim_accel_rebuild(struct sim_snapshot *ss, struct sim_accel *accel) MEMZERO_STRUCT(&ent->space_handle); } } - - /* NOTE: Not rebuilding space since it'll happen during phys step */ } /* ========================== * @@ -349,93 +237,6 @@ INTERNAL void test_clear_level(struct sim_snapshot *world) } } -/* ========================== * - * Release entities - * ========================== */ - -#if 0 -INTERNAL void release_entities_with_prop(struct sim_snapshot *ss_blended, enum sim_ent_prop prop) -{ - struct temp_arena scratch = scratch_begin_no_conflict(); - struct space *space = ss_blended->space; - - struct sim_ent **ents_to_release = arena_dry_push(scratch.arena, struct sim_ent *); - u64 ents_to_release_count = 0; - for (u64 ent_index = 0; ent_index < ss_blended->num_ents_reserved; ++ent_index) { - struct sim_ent *ent = &ss_blended->ents[ent_index]; - if (ent->valid && sim_ent_has_prop(ent, prop)) { - *arena_push(scratch.arena, struct sim_ent *) = ent; - ++ents_to_release_count; - } - } - - /* Release references */ - for (u64 i = 0; i < ents_to_release_count; ++i) { - struct sim_ent *ent = ents_to_release[i]; - /* Release space entry */ - { - struct space_entry *space_entry = space_entry_from_handle(space, ent->space_handle); - if (space_entry->valid) { - space_entry_release(space_entry); - } - } - } - - /* Release from snapshot */ - /* TODO: Breadth first iteration to only release parent entities (since - * child entities will be released along with parent anyway) */ - for (u64 i = 0; i < ents_to_release_count; ++i) { - struct sim_ent *ent = ents_to_release[i]; - if (ent->is_top && !ent->is_root) { - sim_ent_release(ent); - } - } - - scratch_end(scratch); -} -#else -INTERNAL void release_entities_with_prop(struct sim_step_ctx *ctx, enum sim_ent_prop prop) -{ - struct temp_arena scratch = scratch_begin_no_conflict(); - struct sim_snapshot *world = ctx->world; - struct space *space = ctx->accel->space; - - struct sim_ent **ents_to_release = arena_dry_push(scratch.arena, struct sim_ent *); - u64 ents_to_release_count = 0; - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { - struct sim_ent *ent = &world->ents[ent_index]; - if (ent->valid && sim_ent_has_prop(ent, prop)) { - *arena_push(scratch.arena, struct sim_ent *) = ent; - ++ents_to_release_count; - } - } - - /* Release references */ - for (u64 i = 0; i < ents_to_release_count; ++i) { - struct sim_ent *ent = ents_to_release[i]; - /* Release space entry */ - { - struct space_entry *space_entry = space_entry_from_handle(space, ent->space_handle); - if (space_entry->valid) { - space_entry_release(space_entry); - } - } - } - - /* Release from snapshot */ - /* TODO: Breadth first iteration to only release parent entities (since - * child entities will be released along with parent anyway) */ - for (u64 i = 0; i < ents_to_release_count; ++i) { - struct sim_ent *ent = ents_to_release[i]; - if (ent->is_top && !ent->is_root) { - sim_ent_release(ent); - } - } - - scratch_end(scratch); -} -#endif - /* ========================== * * Respond to physics collisions * ========================== */ @@ -551,10 +352,11 @@ void sim_step(struct sim_step_ctx *ctx) struct sim_ent *root = sim_ent_from_handle(world, SIM_ENT_ROOT_HANDLE); /* ========================== * - * Release entities + * Release entities at beginning of frame * ========================== */ - release_entities_with_prop(ctx, SIM_ENT_PROP_RELEASE); + sim_ent_release_all_with_prop(world, SIM_ENT_PROP_RELEASE); + sim_accel_reset(world, ctx->accel); if (ctx->is_master) { /* ========================== * @@ -1394,10 +1196,10 @@ void sim_step(struct sim_step_ctx *ctx) } /* ========================== * - * Release entities + * Release entities at end of frame * ========================== */ - release_entities_with_prop(ctx, SIM_ENT_PROP_RELEASE); + sim_ent_release_all_with_prop(world, SIM_ENT_PROP_RELEASE); /* ========================== * * End frame diff --git a/src/sim_step.h b/src/sim_step.h index c0a0e61c..d352dd80 100644 --- a/src/sim_step.h +++ b/src/sim_step.h @@ -4,45 +4,6 @@ struct space; struct sim_snapshot; struct sim_snapshot_list; -struct sim_lookup; - -/* ========================== * - * Sim lookup - * ========================== */ - - /* Structure used to accelerate up entity lookup (rebuilt every step) */ - /* TODO: Remove this and do something better. Just a hack to de-couple old sim ctx from step. */ - -struct sim_lookup_key { - u64 hash; -}; - -struct sim_lookup_entry { - struct sim_lookup_key key; - struct sim_ent_handle ent; - struct sim_lookup_entry *next; - struct sim_lookup_entry *prev; -}; - -struct sim_lookup_bucket { - struct sim_lookup_entry *first; - struct sim_lookup_entry *last; -}; - -struct sim_lookup { - struct arena arena; - struct sim_lookup_bucket *buckets; - u64 num_buckets; - struct sim_lookup_entry *first_free_entry; -}; - -struct sim_lookup sim_lookup_alloc(u64 num_buckets); -void sim_lookup_release(struct sim_lookup *l); -void sim_lookup_reset(struct sim_lookup *l); - -struct sim_lookup_entry *sim_lookup_get(struct sim_lookup *l, struct sim_lookup_key key); -void sim_lookup_set(struct sim_lookup *l, struct sim_lookup_key key, struct sim_ent_handle handle); -void sim_lookup_remove(struct sim_lookup *l, struct sim_lookup_entry *entry); /* ========================== * * Sim accel @@ -57,7 +18,7 @@ struct sim_accel { struct sim_accel sim_accel_alloc(void); void sim_accel_release(struct sim_accel *accel); -void sim_accel_rebuild(struct sim_snapshot *ss, struct sim_accel *accel); +void sim_accel_reset(struct sim_snapshot *ss, struct sim_accel *accel); /* ========================== * * Sim step diff --git a/src/sock_win32.c b/src/sock_win32.c index 22ae8c45..b83d713a 100644 --- a/src/sock_win32.c +++ b/src/sock_win32.c @@ -5,8 +5,7 @@ #include "scratch.h" #include "string.h" #include "log.h" -#include "app.h" -#include "atomic.h" +#include "gstat.h" #define WIN32_LEAN_AND_MEAN #define UNICODE @@ -414,7 +413,7 @@ struct sock_read_result sock_read(struct sock *sock, struct string read_buff) res.address = sock_address_from_win32_address(ws_addr); if (size >= 0) { - atomic_u64_eval_add_u64(&app_statistics()->sock_bytes_received, size); + gstat_add(GSTAT_SOCK_BYTES_RECEIVED, size); res.data.text = read_buff.text; res.data.len = size; res.valid = true; @@ -440,7 +439,7 @@ void sock_write(struct sock *sock, struct sock_address address, struct string da struct win32_address ws_addr = win32_address_from_sock_address(address); i32 size = sendto(ws->sock, (char *)data.text, data.len, 0, &ws_addr.sa, ws_addr.size); if (size > 0) { - atomic_u64_eval_add_u64(&app_statistics()->sock_bytes_sent, size); + gstat_add(GSTAT_SOCK_BYTES_SENT, size); } #if RTC if (size != (i32)data.len) { diff --git a/src/user.c b/src/user.c index 8fcd8fc6..f537ac08 100644 --- a/src/user.c +++ b/src/user.c @@ -1,5 +1,4 @@ #include "user.h" -#include "app.h" #include "sim.h" #include "sim_ent.h" #include "sim_step.h" @@ -8,7 +7,6 @@ #include "sprite.h" #include "draw.h" #include "intrinsics.h" -#include "app.h" #include "asset_cache.h" #include "string.h" #include "scratch.h" @@ -22,6 +20,8 @@ #include "sock.h" #include "host.h" #include "bitbuff.h" +#include "gstat.h" +#include "app.h" struct bind_state { b32 is_held; /* Is this bind held down this frame */ @@ -362,11 +362,11 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e b32 transmitting = sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_SRC); b32 receiving = sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST); if (transmitting & receiving) { - res.len += string_copy(arena, LIT(" recv & send")).len; + res.len += string_copy(arena, LIT(" synced (send & recv)")).len; } else if (transmitting) { - res.len += string_copy(arena, LIT(" send")).len; + res.len += string_copy(arena, LIT(" synced (send)")).len; } else if (receiving) { - res.len += string_copy(arena, LIT(" recv")).len; + res.len += string_copy(arena, LIT(" synced (recv)")).len; } else { res.len += string_copy(arena, LIT(" local")).len; } @@ -1551,8 +1551,8 @@ INTERNAL void user_update(void) { /* Update network usage stats */ i64 stat_now_ns = sys_time_ns(); - G.net_bytes_read.last_second_end = atomic_u64_eval(&app_statistics()->sock_bytes_received); - G.net_bytes_sent.last_second_end = atomic_u64_eval(&app_statistics()->sock_bytes_sent); + G.net_bytes_read.last_second_end = gstat_get(GSTAT_SOCK_BYTES_RECEIVED); + G.net_bytes_sent.last_second_end = gstat_get(GSTAT_SOCK_BYTES_SENT); if (stat_now_ns - G.last_second_reset_ns > NS_FROM_SECONDS(1)) { G.last_second_reset_ns = stat_now_ns; G.net_bytes_read.last_second = G.net_bytes_read.last_second_end - G.net_bytes_read.last_second_start; @@ -1635,13 +1635,13 @@ INTERNAL void user_update(void) pos.y += spacing; pos.y += spacing; - draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Memory usage: %F MiB"), FMT_FLOAT_P((f64)atomic_u64_eval(&app_statistics()->memory_committed) / 1024 / 1024, 3))); + draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Memory usage: %F MiB"), FMT_FLOAT_P((f64)gstat_get(GSTAT_MEMORY_COMMITTED) / 1024 / 1024, 3))); pos.y += spacing; - draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Virtual memory usage: %F TiB"), FMT_FLOAT_P((f64)atomic_u64_eval(&app_statistics()->memory_reserved) / 1024 / 1024 / 1024 / 1024, 3))); + draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Virtual memory usage: %F TiB"), FMT_FLOAT_P((f64)gstat_get(GSTAT_MEMORY_RESERVED) / 1024 / 1024 / 1024 / 1024, 3))); pos.y += spacing; - draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Arenas allocated: %F"), FMT_UINT(atomic_u64_eval(&app_statistics()->num_arenas)))); + draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Arenas allocated: %F"), FMT_UINT(gstat_get(GSTAT_NUM_ARENAS)))); pos.y += spacing; pos.y += spacing; @@ -1946,6 +1946,7 @@ INTERNAL void sim_snapshot_sync(struct sim_snapshot *local_ss, struct sim_snapsh } } } + sim_ent_release_all_with_prop(local_ss, SIM_ENT_PROP_RELEASE); } @@ -2193,9 +2194,6 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) struct sim_snapshot *prev_local_ss = sim_snapshot_from_tick(local_client, local_client->last_tick); struct sim_snapshot *local_ss = sim_snapshot_alloc(local_client, prev_local_ss, step_tick); - /* Rebuild acceleration tables */ - sim_accel_rebuild(local_ss, &accel); - /* Sync remote ents with client */ { struct sim_ent *local_root = sim_ent_from_handle(local_ss, SIM_ENT_ROOT_HANDLE); @@ -2386,16 +2384,6 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) - - - - - - - - - - /* Publish snapshot to remote clients */ for (u64 i = 0; i < store->num_clients_reserved; ++i) { struct sim_client *client = &store->clients[i];