X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=util.c;h=2151547183b3998578726f2d7f8676899c3222c6;hp=891082bf598e97ba5f27efa3909a6f385ca4c730;hb=f884bd2217992c92f20b1bab5dcdbc20de3de068;hpb=280dfdd3f807532935217722aa9ac74e8194ef5d diff --git a/util.c b/util.c index 891082b..2151547 100644 --- a/util.c +++ b/util.c @@ -166,7 +166,54 @@ static void util_dumpmem(struct memblock_t *memory, uint16_t cols) { } } } -static uint64_t vectors = 0; + +/* + * The following is a VERY tight, efficent, hashtable for integer + * values and keys, and for nothing more. We could make our existing + * hashtable support type-genericness through a void * pointer but, + * ideally that would make things more complicated. We also don't need + * that much of a bloat for something as basic as this. + */ +typedef struct { + size_t key; + size_t value; +} size_entry_t; +#define ST_SIZE 1024 + +typedef size_entry_t **size_table_t; + +size_table_t util_st_new() { + return (size_table_t)memset( + mem_a(sizeof(size_entry_t*) * ST_SIZE), + 0, ST_SIZE * sizeof(size_entry_t*) + ); +} +void util_st_del(size_table_t table) { + size_t i = 0; + for (; i < ST_SIZE; i++) if(table[i]) mem_d(table[i]); + mem_d(table); +} +size_entry_t *util_st_get(size_table_t table, size_t key) { + size_t hash = (key % ST_SIZE); + while (table[hash] && table[hash]->key != key) + hash = (hash + 1) % ST_SIZE; + return table[hash]; +} +void util_st_put(size_table_t table, size_t key, size_t value) { + size_t hash = (key % ST_SIZE); + while (table[hash] && table[hash]->key != key) + hash = (hash + 1) % ST_SIZE; + table[hash] = (size_entry_t*)mem_a(sizeof(size_entry_t)); + table[hash]->key = key; + table[hash]->value = value; +} + +static uint64_t strdups = 0; +static uint64_t vectors = 0; +static uint64_t vector_sizes = 0; +static uint64_t hashtables = 0; +static size_table_t vector_usage = NULL; + void util_meminfo() { struct memblock_t *info; @@ -180,10 +227,6 @@ void util_meminfo() { util_dumpmem(info, OPTS_OPTION_U16(OPTION_MEMDUMPCOLS)); } } - - con_out("Additional Statistics:\n Total vectors used: %lu\n", - vectors - ); if (OPTS_OPTION_BOOL(OPTION_DEBUG) || OPTS_OPTION_BOOL(OPTION_MEMCHK)) { @@ -205,6 +248,40 @@ void util_meminfo() { (mem_at - mem_dt) ); } + + if (OPTS_OPTION_BOOL(OPTION_STATISTICS) || + OPTS_OPTION_BOOL(OPTION_MEMCHK)) { + size_t i=0; + size_t e=1; + + con_out("Additional Statistics:\n\ + Total vectors allocated: %llu\n\ + Total string duplicates: %llu\n\ + Total hashtables allocated: %llu\n\ + Total unique vector sizes: %llu\n", + vectors, + strdups, + hashtables, + vector_sizes + ); + + for (; i < ST_SIZE; i++) { + size_entry_t *entry; + + if (!(entry = vector_usage[i])) + continue; + + con_out(" %u| # of %3u (bytes) vectors: %u\n", + (unsigned)e, + (unsigned)entry->key, + (unsigned)entry->value + ); + e++; + } + } + + if (vector_usage) + util_st_del(vector_usage); } /* @@ -226,6 +303,7 @@ char *_util_Estrdup(const char *s, const char *file, size_t line) { memcpy(ptr, s, len); ptr[len] = '\0'; } + strdups++; return ptr; } @@ -245,6 +323,7 @@ char *_util_Estrdup_empty(const char *s, const char *file, size_t line) { memcpy(ptr, s, len); ptr[len] = '\0'; } + strdups++; return ptr; } @@ -437,10 +516,11 @@ size_t util_strtononcmd(const char *in, char *out, size_t outsz) { /* TODO: rewrite ... when I redo the ve cleanup */ void _util_vec_grow(void **a, size_t i, size_t s) { - vector_t *d = vec_meta(*a); - size_t m = 0; - void *p = NULL; - + vector_t *d = vec_meta(*a); + size_t m = 0; + size_entry_t *e = NULL; + void *p = NULL; + if (*a) { m = 2 * d->allocated + i; p = mem_r(d, s * m + sizeof(vector_t)); @@ -450,6 +530,16 @@ void _util_vec_grow(void **a, size_t i, size_t s) { ((vector_t*)p)->used = 0; vectors++; } + + if (!vector_usage) + vector_usage = util_st_new(); + + if ((e = util_st_get(vector_usage, s))) { + e->value ++; + } else { + util_st_put(vector_usage, s, 1); /* start off with 1 */ + vector_sizes++; + } *a = (vector_t*)p + 1; vec_meta(*a)->allocated = m; @@ -540,6 +630,7 @@ hash_table_t *util_htnew(size_t size) { hashtable->size = size; memset(hashtable->table, 0, sizeof(hash_node_t*) * size); + hashtables++; return hashtable; }