diff --git a/include/core/basalt_memory.h b/include/core/basalt_memory.h index 10073ea..1ef8859 100644 --- a/include/core/basalt_memory.h +++ b/include/core/basalt_memory.h @@ -71,7 +71,7 @@ namespace basalt // Must be freed by user via dealloc with the tags; // MEMORY_TAG_CLASS_STRING | MEMORY_TAG_ZONE_DEBUG | MEMORY_TAG_ALIGN_ANY - char* get_memory_usage_string(void); + char* get_memory_usage_string(u32* slen, char** memstr=nullptr); i64 get_memory_tag_class_name(MEMORY_TAG memory_class, char* out_buf, u64 out_buf_size); i64 get_memory_tag_zone_name(MEMORY_TAG memory_zone, char* out_buf, u64 out_buf_size); diff --git a/src/core/basalt_memory.cpp b/src/core/basalt_memory.cpp index c6703e8..430b304 100644 --- a/src/core/basalt_memory.cpp +++ b/src/core/basalt_memory.cpp @@ -80,9 +80,9 @@ void basalt::mem::dealloc(void* ptr, u64 num_bytes, MEMORY_TAG tag) if (ptr == nullptr) return; _mm_free(ptr); - basalt_memory_state.alloc_total += num_bytes; - basalt_memory_state.class_alloc[(MEMORY_TAG_MASK_CLASS & tag) >> MEMORY_TAG_SHIFT_CLASS] += num_bytes; - basalt_memory_state.zone_alloc[(MEMORY_TAG_MASK_ZONE & tag) >> MEMORY_TAG_SHIFT_ZONE] += num_bytes; + basalt_memory_state.alloc_total -= num_bytes; + basalt_memory_state.class_alloc[(MEMORY_TAG_MASK_CLASS & tag) >> MEMORY_TAG_SHIFT_CLASS] -= num_bytes; + basalt_memory_state.zone_alloc[(MEMORY_TAG_MASK_ZONE & tag) >> MEMORY_TAG_SHIFT_ZONE] -= num_bytes; } void* basalt::mem::setzero(void* dst, u64 num_bytes) @@ -125,6 +125,11 @@ f64 get_eng_unit(f64 x, char* unit) constexpr i8 order_index_offset = 5; const char units[] = {'f', 'p', 'n', 'u', 'm', ' ', 'K', 'M', 'G', 'T', 'P', 'E', 'Y'}; i8 order = 0; + if (x == 0) + { + *unit = units[order_index_offset]; + return x; + } while (x > 1000.0 && (order < (sizeof(units) - sizeof(char) * (order_index_offset-1)))) { order++; @@ -139,47 +144,54 @@ f64 get_eng_unit(f64 x, char* unit) return x; } -char* basalt::mem::get_memory_usage_string(void) +char* basalt::mem::get_memory_usage_string(u32* slen, char** pout) { constexpr size_t buffer_size = 2048; - static i32 class_pad_amt = 0; - if (class_pad_amt) + i32 pad_amt = 0; + for (u32 i = 0; i < MEMORY_TAG_CLASS_MAX_BUILTIN; ++i) { - for (u32 i = 0; i < MEMORY_TAG_CLASS_MAX_BUILTIN; ++i) - class_pad_amt = class_pad_amt < basalt_memory_class_name_lengths[i] ? basalt_memory_class_name_lengths[i] : class_pad_amt; - const u32 num_class_user_digits = (u32)ceilf(log10f(MEMORY_TAG_CLASS_MAX - MEMORY_TAG_CLASS_MAX_BUILTIN)); - class_pad_amt = class_pad_amt < num_class_user_digits ? num_class_user_digits : class_pad_amt; + if (basalt_memory_state.class_alloc[i] != 0) + pad_amt = pad_amt < basalt_memory_class_name_lengths[i] ? basalt_memory_class_name_lengths[i] : pad_amt; } - static i32 zone_pad_amt = 0; - if (zone_pad_amt) + const u32 num_class_user_digits = (u32)ceilf(log10f(MEMORY_TAG_CLASS_MAX - MEMORY_TAG_CLASS_MAX_BUILTIN)) + 5; + pad_amt = pad_amt < num_class_user_digits ? num_class_user_digits : pad_amt; + + for (u32 i = 0; i < MEMORY_TAG_ZONE_MAX_BUILTIN; ++i) { - for (u32 i = 0; i < MEMORY_TAG_ZONE_MAX_BUILTIN; ++i) - zone_pad_amt = zone_pad_amt < basalt_memory_zone_name_lengths[i] ? basalt_memory_zone_name_lengths[i] : zone_pad_amt; - const u32 num_zone_user_digits = (u32)ceilf(log10f(MEMORY_TAG_ZONE_MAX - MEMORY_TAG_ZONE_MAX_BUILTIN)); - zone_pad_amt = zone_pad_amt < num_zone_user_digits ? num_zone_user_digits : zone_pad_amt; + if (basalt_memory_state.zone_alloc[i] != 0) + pad_amt = pad_amt < basalt_memory_zone_name_lengths[i] ? basalt_memory_zone_name_lengths[i] : pad_amt; } + const u32 num_zone_user_digits = (u32)ceilf(log10f(MEMORY_TAG_ZONE_MAX - MEMORY_TAG_ZONE_MAX_BUILTIN)) + 5; + pad_amt = pad_amt < num_zone_user_digits ? num_zone_user_digits : pad_amt; size_t offset = 0; - char* ret = (char*)basalt::mem::alloc(buffer_size*sizeof(char), + *slen = buffer_size * sizeof(char); + char* ret = (char*)basalt::mem::alloc(*slen, MEMORY_TAG_CLASS_STRING | MEMORY_TAG_ZONE_DEBUG | MEMORY_TAG_ALIGN_ANY); + if (pout != nullptr) + *pout = ret; char name_buf[256]; char unit = ' '; f64 val = get_eng_unit(basalt_memory_state.alloc_total, &unit); - offset += snprintf(ret+offset, buffer_size - offset - 1, "Total memory usage: %6.2f %cB\nMemory usage by class:\n", val, unit); + offset += snprintf(ret+offset, buffer_size - offset - 1, "Total memory usage: %6.2f %cB\n\tMemory usage by class:\n", val, unit); for (u32 i = 0; i <= MEMORY_TAG_CLASS_MAX; ++i) { + if (basalt_memory_state.class_alloc[i] == 0) + continue; val = get_eng_unit(basalt_memory_state.class_alloc[i], &unit); name_buf[get_memory_tag_class_name(i << MEMORY_TAG_SHIFT_CLASS, name_buf, sizeof(name_buf)-1)] = '\0'; - offset += snprintf(ret+offset, buffer_size - offset - 1, "%-*s: %6.2f %cB\n", class_pad_amt, name_buf, val, unit); + offset += snprintf(ret+offset, buffer_size - offset - 1, "\t\t%-*s: %6.2f %cB\n", pad_amt, name_buf, val, unit); } - offset += snprintf(ret+offset, buffer_size - offset - 1, "Memory usage by location:\n"); - for (u32 i = 0; i <= MEMORY_TAG_CLASS_MAX; ++i) + offset += snprintf(ret+offset, buffer_size - offset - 1, "\tMemory usage by location:\n"); + for (u32 i = 0; i <= MEMORY_TAG_ZONE_MAX; ++i) { + if (basalt_memory_state.zone_alloc[i] == 0) + continue; val = get_eng_unit(basalt_memory_state.zone_alloc[i], &unit); name_buf[get_memory_tag_zone_name(i << MEMORY_TAG_SHIFT_ZONE, name_buf, sizeof(name_buf) - 1)] = '\0'; - offset += snprintf(ret + offset, buffer_size - offset - 1, "%-*s: %6.2f %cB\n", zone_pad_amt, name_buf, val, unit); + offset += snprintf(ret+offset, buffer_size - offset - 1, "\t\t%-*s: %6.2f %cB\n", pad_amt, name_buf, val, unit); } ret[offset] = '\0'; @@ -196,10 +208,10 @@ i64 basalt::mem::get_memory_tag_class_name(MEMORY_TAG memory_class, char* out_bu if (memory_class < MEMORY_TAG_CLASS_MAX_BUILTIN) { - if (out_buf_size < basalt_memory_class_name_lengths[memory_class]) + if (out_buf_size <= basalt_memory_class_name_lengths[memory_class]) return 0; - memcpy(out_buf, basalt_memory_class_names[memory_class], basalt_memory_class_name_lengths[memory_class]); - return basalt_memory_class_name_lengths[memory_class]; + memcpy(out_buf, basalt_memory_class_names[memory_class], basalt_memory_class_name_lengths[memory_class]+1); + return basalt_memory_class_name_lengths[memory_class]+1; } memory_class = user_index_max - memory_class; @@ -216,15 +228,15 @@ i64 basalt::mem::get_memory_tag_class_name(MEMORY_TAG memory_class, char* out_bu i64 basalt::mem::get_memory_tag_zone_name(MEMORY_TAG zone_class, char* out_buf, u64 out_buf_size) { constexpr u16 user_index_max = MEMORY_TAG_CLASS_MAX - MEMORY_TAG_CLASS_MAX_BUILTIN + 1; + zone_class = (zone_class & MEMORY_TAG_MASK_ZONE) >> MEMORY_TAG_SHIFT_ZONE; if (zone_class > user_index_max) return 0; - zone_class = (zone_class & MEMORY_TAG_MASK_ZONE) >> MEMORY_TAG_SHIFT_ZONE; if (zone_class < MEMORY_TAG_ZONE_MAX_BUILTIN) { - if (out_buf_size < basalt_memory_zone_name_lengths[zone_class]) + if (out_buf_size <= basalt_memory_zone_name_lengths[zone_class]) return 0; - memcpy(out_buf, basalt_memory_zone_names[zone_class], basalt_memory_zone_name_lengths[zone_class]); - return basalt_memory_zone_name_lengths[zone_class]; + memcpy(out_buf, basalt_memory_zone_names[zone_class], basalt_memory_zone_name_lengths[zone_class]+1); + return basalt_memory_zone_name_lengths[zone_class]+1; } zone_class = user_index_max - zone_class;