Skip to content

Commit 4e7dc5c

Browse files
committed
Dump largest refc binaries on oom crashes
Signed-off-by: Paul Guyot <[email protected]>
1 parent 6a6decc commit 4e7dc5c

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
@@ -1297,7 +1297,7 @@ COLD_FUNC void context_dump(Context *ctx)
12971297
fprintf(stderr, "process_count = %zu\n", process_count);
12981298
fprintf(stderr, "ports_count = %zu\n", ports_count);
12991299
fprintf(stderr, "atoms_count = %zu\n", atom_table_count(glb->atom_table));
1300-
fprintf(stderr, "refc_binary_total_size = %zu\n", refc_binary_total_size(ctx));
1300+
refc_binary_dump_info(ctx);
13011301
}
13021302
fprintf(stderr, "\n\n**End Of Crash Report**\n");
13031303
}

src/libAtomVM/refc_binary.c

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

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)