util: Add function print information about a ralloc tree
In release mode print the ralloc tree header pointers. In debug mode, will look at the child allocations recursively checking for the canary values. In most cases this should work and give us extra information about the type of the subtree (GC, Linear) and the allocation sizes. For example, calling it at the end of spirv_to_nir() will output the following tree with a summary at the end (lines elided to focus on the general structure of the output) ``` 0xca8d00 (472 bytes) 0xdf2c60 (32 bytes) 0xdf2c00 (32 bytes) 0xdf2ba0 (32 bytes) 0xdf2b40 (32 bytes) (...) 0xcde8b0 (64 bytes) 0xcde760 (72 bytes) 0xd2de40 (168 bytes) 0xcce660 (64 bytes) 0xcce510 (72 bytes) 0xcce5a0 (120 bytes) 0xcce490 (64 bytes) (...) 0xcbc450 (456 bytes) 0xdf55c0 (160 bytes) 0xdf5730 (72 bytes) 0xdf57c0 (80 bytes) 0xdf5530 (72 bytes) 0xdf56a0 (80 bytes) (...) 0xcbe840 (128 bytes) 0xcc4310 (4 bytes) 0xcbc660 (536 bytes) (gc context) 0xde6b40 (32576 bytes) (gc slab or large block) 0xddb160 (32704 bytes) (gc slab or large block) 0xdc8d50 (32704 bytes) (gc slab or large block) (...) 0xcde9a0 (32704 bytes) (gc slab or large block) 0xcd6720 (32704 bytes) (gc slab or large block) 0xcce6e0 (32768 bytes) (gc slab or large block) 0xcbc330 (72 bytes) 0xd680a0 (208 bytes) 0xca9010 (78560 bytes) 0xca8f20 (176 bytes) ==== RALLOC INFO ptr=0xca8d30 info=0xca8d00 ralloc allocations = 4714 - linear = 0 - gc = 23 - other = 4691 content bytes = 1055139 ralloc metadata bytes = 226272 linear metadata bytes = 0 ==== ``` There's a flag to pass so only the summary at the end is printed. Acked-by: Marek Olšák <marek.olsak@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25482>
This commit is contained in:
@@ -1276,3 +1276,121 @@ linear_zalloc_child_array(linear_ctx *ctx, size_t size, unsigned count)
|
||||
|
||||
return linear_zalloc_child(ctx, size * count);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
FILE *f;
|
||||
unsigned indent;
|
||||
|
||||
unsigned ralloc_count;
|
||||
unsigned linear_count;
|
||||
unsigned gc_count;
|
||||
|
||||
/* These don't include padding or metadata from suballocators. */
|
||||
unsigned content_bytes;
|
||||
unsigned ralloc_metadata_bytes;
|
||||
unsigned linear_metadata_bytes;
|
||||
unsigned gc_metadata_bytes;
|
||||
|
||||
bool inside_linear;
|
||||
bool inside_gc;
|
||||
} ralloc_print_info_state;
|
||||
|
||||
static void
|
||||
ralloc_print_info_helper(ralloc_print_info_state *state, const ralloc_header *info)
|
||||
{
|
||||
FILE *f = state->f;
|
||||
|
||||
if (f) {
|
||||
for (unsigned i = 0; i < state->indent; i++) fputc(' ', f);
|
||||
fprintf(f, "%p", info);
|
||||
}
|
||||
|
||||
/* TODO: Account for padding used in various places. */
|
||||
|
||||
#ifndef NDEBUG
|
||||
assert(info->canary == CANARY);
|
||||
if (f) fprintf(f, " (%d bytes)", info->size);
|
||||
state->content_bytes += info->size;
|
||||
state->ralloc_metadata_bytes += sizeof(ralloc_header);
|
||||
|
||||
const void *ptr = PTR_FROM_HEADER(info);
|
||||
const linear_ctx *lin_ctx = ptr;
|
||||
const gc_ctx *gc_ctx = ptr;
|
||||
|
||||
if (lin_ctx->magic == LMAGIC_CONTEXT) {
|
||||
if (f) fprintf(f, " (linear context)");
|
||||
assert(!state->inside_gc && !state->inside_linear);
|
||||
state->inside_linear = true;
|
||||
state->linear_metadata_bytes += sizeof(linear_ctx);
|
||||
state->content_bytes -= sizeof(linear_ctx);
|
||||
state->linear_count++;
|
||||
} else if (gc_ctx->canary == GC_CONTEXT_CANARY) {
|
||||
if (f) fprintf(f, " (gc context)");
|
||||
assert(!state->inside_gc && !state->inside_linear);
|
||||
state->inside_gc = true;
|
||||
state->gc_metadata_bytes += sizeof(gc_block_header);
|
||||
} else if (state->inside_linear) {
|
||||
const linear_node_canary *lin_node = ptr;
|
||||
if (lin_node->magic == LMAGIC_NODE) {
|
||||
if (f) fprintf(f, " (linear node buffer)");
|
||||
state->content_bytes -= sizeof(linear_node_canary);
|
||||
state->linear_metadata_bytes += sizeof(linear_node_canary);
|
||||
state->linear_count++;
|
||||
}
|
||||
} else if (state->inside_gc) {
|
||||
if (f) fprintf(f, " (gc slab or large block)");
|
||||
state->gc_count++;
|
||||
}
|
||||
#endif
|
||||
|
||||
state->ralloc_count++;
|
||||
if (f) fprintf(f, "\n");
|
||||
|
||||
const ralloc_header *c = info->child;
|
||||
state->indent += 2;
|
||||
while (c != NULL) {
|
||||
ralloc_print_info_helper(state, c);
|
||||
c = c->next;
|
||||
}
|
||||
state->indent -= 2;
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (lin_ctx->magic == LMAGIC_CONTEXT) state->inside_linear = false;
|
||||
else if (gc_ctx->canary == GC_CONTEXT_CANARY) state->inside_gc = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ralloc_print_info(FILE *f, const void *p, unsigned flags)
|
||||
{
|
||||
ralloc_print_info_state state = {
|
||||
.f = ((flags & RALLOC_PRINT_INFO_SUMMARY_ONLY) == 1) ? NULL : f,
|
||||
};
|
||||
|
||||
const ralloc_header *info = get_header(p);
|
||||
ralloc_print_info_helper(&state, info);
|
||||
|
||||
fprintf(f, "==== RALLOC INFO ptr=%p info=%p\n"
|
||||
"ralloc allocations = %d\n"
|
||||
" - linear = %d\n"
|
||||
" - gc = %d\n"
|
||||
" - other = %d\n",
|
||||
p, info,
|
||||
state.ralloc_count,
|
||||
state.linear_count,
|
||||
state.gc_count,
|
||||
state.ralloc_count - state.linear_count - state.gc_count);
|
||||
|
||||
if (state.content_bytes) {
|
||||
fprintf(f,
|
||||
"content bytes = %d\n"
|
||||
"ralloc metadata bytes = %d\n"
|
||||
"linear metadata bytes = %d\n",
|
||||
state.content_bytes,
|
||||
state.ralloc_metadata_bytes,
|
||||
state.linear_metadata_bytes);
|
||||
}
|
||||
|
||||
fprintf(f, "====\n");
|
||||
}
|
||||
|
||||
|
@@ -700,6 +700,12 @@ bool linear_strcat(linear_ctx *ctx, char **dest, const char *str);
|
||||
#define linear_zalloc_array(ctx, type, count) \
|
||||
((type *) linear_zalloc_child_array(ctx, sizeof(type), count))
|
||||
|
||||
enum {
|
||||
RALLOC_PRINT_INFO_SUMMARY_ONLY = 1 << 0,
|
||||
};
|
||||
|
||||
void ralloc_print_info(FILE *f, const void *p, unsigned flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user