mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-12 23:31:38 -07:00
198 lines
5.4 KiB
C
198 lines
5.4 KiB
C
// Copyright (c) 2024 Epic Games Tools
|
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
|
|
|
////////////////////////////////
|
|
// NOTE(allen): Dev Arena
|
|
|
|
#if ENABLE_DEV
|
|
|
|
internal void
|
|
arena_annotate_push__dev(Arena *arena, U64 size, void *ptr){
|
|
ArenaDev *dev = arena->dev;
|
|
if (dev != 0 && ptr != 0){
|
|
//- read location
|
|
char *file_name = 0;
|
|
U64 line_number = 0;
|
|
tctx_read_srcloc(&file_name, &line_number);
|
|
tctx_write_srcloc(0, 0);
|
|
|
|
//- profile
|
|
ArenaProf *prof = dev->prof;
|
|
if (prof != 0){
|
|
// c string -> string
|
|
String8 file_name_str = str8_lit("(null)");
|
|
if (file_name != 0){
|
|
file_name_str = str8_cstring(file_name);
|
|
}
|
|
// record
|
|
arena_prof_inc_counters__dev(dev->arena, prof, file_name_str, line_number, size, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void
|
|
arena_annotate_absorb__dev(Arena *arena, Arena *sub){
|
|
ArenaDev *dev = arena->dev;
|
|
ArenaDev *sub_dev = sub->dev;
|
|
if (dev != 0 && sub_dev != 0){
|
|
//- merge profiles
|
|
ArenaProf *prof = dev->prof;
|
|
ArenaProf *sub_prof = sub_dev->prof;
|
|
if (prof != 0 && sub_prof != 0){
|
|
for (ArenaProfNode *sub_node = sub_prof->first;
|
|
sub_node != 0;
|
|
sub_node = sub_node->next){
|
|
arena_prof_inc_counters__dev(dev->arena, prof, sub_node->file_name, sub_node->line,
|
|
sub_node->size, sub_node->count);
|
|
}
|
|
}
|
|
}
|
|
//- release the sub dev memory
|
|
if (sub_dev != 0){
|
|
arena_release(sub_dev->arena);
|
|
}
|
|
}
|
|
|
|
internal ArenaDev*
|
|
arena_equip__dev(Arena *arena){
|
|
ArenaDev *result = arena->dev;
|
|
if (result == 0){
|
|
Arena *dev_arena = arena_alloc();
|
|
ArenaDev *dev = (ArenaDev*)arena_push__impl(dev_arena, sizeof(ArenaDev));
|
|
MemoryZeroStruct(dev);
|
|
dev->arena = dev_arena;
|
|
arena->dev = dev;
|
|
result = dev;
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
internal void
|
|
arena_equip_profile__dev(Arena *arena){
|
|
ArenaDev *dev = arena_equip__dev(arena);
|
|
if (dev->prof == 0){
|
|
dev->prof = (ArenaProf*)arena_push__impl(dev->arena, sizeof(ArenaProf));
|
|
MemoryZeroStruct(dev->prof);
|
|
}
|
|
}
|
|
|
|
internal void
|
|
arena_print_profile__dev(Arena *arena, Arena *out_arena, String8List *out){
|
|
Assert(arena != out_arena);
|
|
|
|
//- get dev & disable
|
|
ArenaDev *dev = arena->dev;
|
|
arena->dev = 0;
|
|
|
|
//- get prof
|
|
ArenaProf *prof = (dev != 0)?dev->prof:0;
|
|
|
|
//- not equipped with prof
|
|
if (prof == 0){
|
|
str8_list_push(out_arena, out, str8_lit("not equipped with a memory profile\n"));
|
|
}
|
|
|
|
//- print prof
|
|
if (prof != 0){
|
|
Temp scratch = temp_begin(dev->arena);
|
|
|
|
//- make flat array
|
|
U64 note_count = prof->count;
|
|
ArenaProfNode **notes = push_array_no_zero__no_annotation(scratch.arena, ArenaProfNode*, note_count);
|
|
{
|
|
ArenaProfNode **note_ptr = notes;
|
|
for (ArenaProfNode *node = prof->first;
|
|
node != 0;
|
|
node = node->next, note_ptr += 1){
|
|
*note_ptr = node;
|
|
}
|
|
}
|
|
|
|
//- file name size
|
|
U64 max_file_name_size = 0;
|
|
{
|
|
ArenaProfNode **note_ptr = notes;
|
|
for (U64 i = 0; i < note_count; i += 1, note_ptr += 1){
|
|
max_file_name_size = Max(max_file_name_size, (**note_ptr).file_name.size);
|
|
}
|
|
}
|
|
|
|
//- sort (> size, < [address])
|
|
for (U64 i = 0; i < note_count; i += 1){
|
|
ArenaProfNode **i_note = notes + i;
|
|
ArenaProfNode **min_note = i_note;
|
|
for (U64 j = i + 1; j < note_count; j += 1){
|
|
ArenaProfNode **j_note = notes + j;
|
|
if ((**j_note).size > (**min_note).size ||
|
|
((**j_note).size == (**min_note).size && *j_note < *min_note)){
|
|
min_note = j_note;
|
|
}
|
|
}
|
|
if (min_note != i_note){
|
|
ArenaProfNode *t = *i_note;
|
|
*i_note = *min_note;
|
|
*min_note = t;
|
|
}
|
|
}
|
|
|
|
//- total size
|
|
U64 total_size = 0;
|
|
{
|
|
ArenaProfNode **note_ptr = notes;
|
|
for (U64 i = 0; i < note_count; i += 1, note_ptr += 1){
|
|
ArenaProfNode *note = *note_ptr;
|
|
total_size += note->size;
|
|
}
|
|
}
|
|
|
|
//- print
|
|
{
|
|
str8_list_pushf(out_arena, out, "memory total: %llu\n", total_size);
|
|
|
|
ArenaProfNode **note_ptr = notes;
|
|
for (U64 i = 0; i < note_count; i += 1, note_ptr += 1){
|
|
ArenaProfNode *note = *note_ptr;
|
|
String8 location = push_str8f(scratch.arena, "%S:%5llu:",
|
|
note->file_name, note->line);
|
|
F32 percent = 100.f*((F32)note->size)/total_size;
|
|
str8_list_pushf(out_arena, out, "%*.*s %12llu %5.2f%% [%5llu]\n",
|
|
max_file_name_size + 7, str8_varg(location),
|
|
note->size, percent, note->count);
|
|
}
|
|
}
|
|
|
|
temp_end(scratch);
|
|
}
|
|
|
|
//- restore dev
|
|
arena->dev = dev;
|
|
}
|
|
|
|
internal void
|
|
arena_prof_inc_counters__dev(Arena *dev_arena, ArenaProf *prof, String8 file_name, U64 line,
|
|
U64 size, U64 count){
|
|
// find existing profile node
|
|
ArenaProfNode *prof_node = 0;
|
|
for (ArenaProfNode *node = prof->first;
|
|
node != 0;
|
|
node = node->next){
|
|
if (node->line == line && str8_match(file_name, node->file_name, 0)){
|
|
prof_node = node;
|
|
break;
|
|
}
|
|
}
|
|
// make new histogram node if necessary
|
|
if (prof_node == 0){
|
|
prof_node = (ArenaProfNode*)arena_push(dev_arena, sizeof(*prof_node));
|
|
SLLQueuePush(prof->first, prof->last, prof_node);
|
|
prof->count += 1;
|
|
prof_node->file_name = file_name;
|
|
prof_node->line = line;
|
|
}
|
|
// record this allocation
|
|
prof_node->size += size;
|
|
prof_node->count += count;
|
|
}
|
|
|
|
#endif
|