atproto relay implementation in zig zlay.waow.tech

fix: use mallinfo2 via extern decl for accurate metrics >2 GiB

mallinfo's int fields were overflowing at 2 GiB, making arena and
mmap metrics useless. the runtime glibc (2.36) has mallinfo2 but
zig's bundled cross-compile headers don't declare it. manual extern
struct declaration bypasses the header issue.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+17 -4
+17 -4
src/broadcaster.zig
··· 628 628 return fbs.getWritten(); 629 629 } 630 630 631 - const malloc_h = @cImport(@cInclude("malloc.h")); 631 + // glibc mallinfo2 (available since 2.33) — declared manually because zig's 632 + // bundled cross-compile headers may not include it, but the runtime glibc does. 633 + // uses usize fields (no 2 GiB overflow like mallinfo's int fields). 634 + const Mallinfo2 = extern struct { 635 + arena: usize, // bytes claimed from OS (non-mmap) 636 + ordblks: usize, 637 + smblks: usize, 638 + hblks: usize, 639 + hblkhd: usize, // bytes in mmap regions 640 + usmblks: usize, 641 + fsmblks: usize, 642 + uordblks: usize, // bytes in use (allocated) 643 + fordblks: usize, // free bytes in arena (fragmentation) 644 + keepcost: usize, 645 + }; 646 + extern "c" fn mallinfo2() Mallinfo2; 632 647 633 648 fn appendProcMetrics(w: anytype) void { 634 649 // RSS from /proc/self/statm (field[1] * page_size) ··· 683 698 } else |_| {} 684 699 685 700 // glibc malloc arena stats — distinguishes in-use heap from fragmentation 686 - // uses mallinfo (not mallinfo2) for older glibc compat; int fields cap at 2 GiB 687 - // but that's enough to distinguish leak vs fragmentation patterns 688 - const mi = malloc_h.mallinfo(); 701 + const mi = mallinfo2(); 689 702 std.fmt.format(w, 690 703 \\# TYPE relay_malloc_arena_bytes gauge 691 704 \\# HELP relay_malloc_arena_bytes total bytes claimed from OS by malloc