X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=util.c;h=2151547183b3998578726f2d7f8676899c3222c6;hp=c8d50f5b5fbc15fbff326efbaa45a40f4f734d49;hb=f884bd2217992c92f20b1bab5dcdbc20de3de068;hpb=10dd7aacfe87f97e10d61dff343e00b9c03eac69 diff --git a/util.c b/util.c index c8d50f5..2151547 100644 --- a/util.c +++ b/util.c @@ -167,10 +167,56 @@ static void util_dumpmem(struct memblock_t *memory, uint16_t cols) { } } +/* + * 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; - if (OPTS_OPTION_BOOL(OPTION_DEBUG)) { for (info = mem_start; info; info = info->next) { con_out("lost: %u (bytes) at %s:%u\n", @@ -202,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); } /* @@ -223,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; } @@ -242,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; } @@ -434,14 +516,32 @@ 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 = *a ? 2 * d->allocated +i : i+1; - void *p = mem_r((*a ? d : NULL), s * m + sizeof(vector_t)); - - if (!*a) + 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)); + } else { + m = i + 1; + p = mem_a(s * m + sizeof(vector_t)); ((vector_t*)p)->used = 0; - *a = (vector_t*)p + 1; + 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; } @@ -491,7 +591,7 @@ GMQCC_INLINE size_t util_hthash(hash_table_t *ht, const char *key) { return (size_t) (hash % ht->size); } -hash_node_t *_util_htnewpair(const char *key, void *value) { +static hash_node_t *_util_htnewpair(const char *key, void *value) { hash_node_t *node; if (!(node = (hash_node_t*)mem_a(sizeof(hash_node_t)))) return NULL; @@ -530,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; }