Skip to content

Commit 02f5356

Browse files
committed
Dump largest refc binaries on oom crashes
Signed-off-by: Paul Guyot <[email protected]>
1 parent 6779b69 commit 02f5356

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed

src/libAtomVM/context.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1300,7 +1300,7 @@ COLD_FUNC void context_dump(Context *ctx)
13001300
fprintf(stderr, "process_count = %zu\n", process_count);
13011301
fprintf(stderr, "ports_count = %zu\n", ports_count);
13021302
fprintf(stderr, "atoms_count = %zu\n", atom_table_count(glb->atom_table));
1303-
fprintf(stderr, "refc_binary_total_size = %zu\n", refc_binary_total_size(ctx));
1303+
refc_binary_dump_info(ctx);
13041304
}
13051305
fprintf(stderr, "\n\n**End Of Crash Report**\n");
13061306
}

src/libAtomVM/refc_binary.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,86 @@ size_t refc_binary_total_size(Context *ctx)
146146
synclist_unlock(&ctx->global->refc_binaries);
147147
return size;
148148
}
149+
150+
COLD_FUNC void refc_binary_dump_info(Context *ctx)
151+
{
152+
struct ListHead *item;
153+
struct ListHead *refc_binaries = synclist_rdlock(&ctx->global->refc_binaries);
154+
155+
// Note: This only counts non-const refc binaries (ones that allocate memory).
156+
// Const binaries (created by term_from_const_binary) point to existing data
157+
// and are never added to the global refc_binaries list, so they don't appear here.
158+
159+
// First pass: count and calculate total size
160+
size_t count = 0;
161+
size_t total_size = 0;
162+
LIST_FOR_EACH (item, refc_binaries) {
163+
struct RefcBinary *refc = GET_LIST_ENTRY(item, struct RefcBinary, head);
164+
count++;
165+
total_size += refc->size;
166+
}
167+
168+
fprintf(stderr, "refc_binary_count = %d\n", (int) count);
169+
fprintf(stderr, "refc_binary_total_size = %d\n", (int) total_size);
170+
171+
if (count == 0) {
172+
synclist_unlock(&ctx->global->refc_binaries);
173+
return;
174+
}
175+
176+
// Find top 5 largest binaries
177+
#define TOP_N 5
178+
struct RefcBinary *top[TOP_N] = { NULL };
179+
size_t top_indices[TOP_N] = { 0 };
180+
181+
size_t index = 0;
182+
LIST_FOR_EACH (item, refc_binaries) {
183+
struct RefcBinary *refc = GET_LIST_ENTRY(item, struct RefcBinary, head);
184+
185+
// Try to insert into top 5
186+
for (size_t i = 0; i < TOP_N; i++) {
187+
if (top[i] == NULL || refc->size > top[i]->size) {
188+
// Shift down
189+
for (size_t j = TOP_N - 1; j > i; j--) {
190+
top[j] = top[j - 1];
191+
top_indices[j] = top_indices[j - 1];
192+
}
193+
top[i] = refc;
194+
top_indices[i] = index;
195+
break;
196+
}
197+
}
198+
index++;
199+
}
200+
201+
// Display top binaries
202+
fprintf(stderr, "\nTop %d largest refc binaries:\n", TOP_N);
203+
for (size_t i = 0; i < TOP_N && top[i] != NULL; i++) {
204+
struct RefcBinary *refc = top[i];
205+
fprintf(stderr, " [%zu] size=%d bytes (%.1f%%), refcount=%d",
206+
top_indices[i],
207+
(int) refc->size,
208+
(double) refc->size * 100.0 / (double) total_size,
209+
(int) refc->ref_count);
210+
211+
if (refc->resource_type) {
212+
fprintf(stderr, " [resource]");
213+
}
214+
215+
// Print first 32 bytes as hex
216+
fprintf(stderr, "\n data: ");
217+
size_t print_size = refc->size < 32 ? refc->size : 32;
218+
for (size_t j = 0; j < print_size; j++) {
219+
fprintf(stderr, "%02x", refc->data[j]);
220+
if (j % 4 == 3 && j < print_size - 1) {
221+
fprintf(stderr, " ");
222+
}
223+
}
224+
if (refc->size > 32) {
225+
fprintf(stderr, "...");
226+
}
227+
fprintf(stderr, "\n");
228+
}
229+
230+
synclist_unlock(&ctx->global->refc_binaries);
231+
}

src/libAtomVM/refc_binary.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,16 @@ term refc_binary_create_binary_info(Context *ctx);
142142
*/
143143
size_t refc_binary_total_size(Context *ctx);
144144

145+
/**
146+
* @brief Dump detailed information about reference counted binaries
147+
*
148+
* @details This function prints diagnostic information including the count,
149+
* total size, and details about the top 5 largest binaries including
150+
* their first bytes. Used for debugging memory issues.
151+
* @param ctx the context
152+
*/
153+
COLD_FUNC void refc_binary_dump_info(Context *ctx);
154+
145155
#ifdef __cplusplus
146156
}
147157
#endif

0 commit comments

Comments
 (0)