Instance Health, Footprint and Memory Leaks
A healthy endpoint can hide a growing heap, leaked subscriptions, too many processes or an oversized app. Reaktor needs both fleet health and evidence about each application instance. Every measurement names its runtime, release, activation, collector, unit, observation interval and scope.
Status: existing infrastructure collects JVM/host/container metrics; DevTools vitals and Crashlytics adapters supply selected client signals; the legacy debug Measure integration is pending removal. The catalog below defines the required operating coverage. It does not claim that every row is wired on every platform.
Footprint and instance catalog
| Family | Required measurements | Scope and interpretation |
|---|---|---|
| App/build size | Download/compressed bytes, installed/unpacked bytes, executable/code, native libraries, resources/assets, dependencies and symbols; build-over-build delta | Separate APK/AAB, IPA, web chunks, JAR/distribution and container image. Record device/ABI, build mode, compression and whether symbols are shipped |
| Instance inventory | Desired/ready replicas, process count, start time, uptime, restarts, exit reason, image/artifact ID | Group by application/deployment and process role. Distinguish sidecars, helpers and app workers; reconcile observed count against topology |
| CPU and scheduling | CPU time/utilization, capacity/limits, throttling, runnable threads, event-loop lag | State normalization: one core, allocated cores or host total. Include contention and generator/profiler overhead |
| Threads/tasks | OS thread count, Java platform/virtual-thread observations where supported, blocked/waiting/runnable states, executor queue, coroutines/actors and mailbox backlog | Processes, threads, coroutines and actors are different counts. A thread dump may omit logical coroutine ancestry |
| Managed memory | Heap used/committed/max, post-GC live set, allocation rate, object counts, retained bytes and GC pauses/cycles | Used is not committed; committed is not resident; allocation volume is not retained volume |
| Native/process memory | RSS, PSS where supported, physical footprint, swap, mapped/shared/private pages, stacks, direct buffers, native/FFI allocations, metaspace and code cache | Preserve platform metric semantics. Never add overlapping measures or compare Android PSS to iOS footprint as if identical |
| Container/host memory | Working set, limit, pressure, OOM kills and host headroom | Container accounting includes more than the application heap; heap tuning must leave native/stack/runtime headroom |
| Resources | Open file descriptors/handles and limits, sockets, connection pools, disk/temp/cache bytes, I/O latency/throughput | Check idle return and disposal, not only peak values |
| User experience | Cold/warm startup, frame deadline misses, stalls, crashes, ANRs, background/foreground behavior, network durations/errors | Record display refresh interval, device tier, thermal/power state and session sampling |
| Graph lifecycle | Active scopes/activations, pending work, retained subscriptions/interceptors, open capabilities, cancellation/drain/close outcomes | After detach, resource counts should return to an explained steady-state baseline |
App size is a build artifact measurement; memory is runtime footprint. Process count is an inventory measurement; coroutine count is a runtime model measurement. Do not collapse them into a single health score that conceals a missing collector.
Platform collection plan
| Runtime | Baseline collection | Deeper investigation |
|---|---|---|
| JVM server/desktop | Existing runtime/host metrics, management APIs, container limits and process inventory | JFR/JMC, thread dumps, heap retention analysis, NMT and native profiler |
| Android | Native DevTools frame/memory/startup observations in debug builds; Crashlytics crashes/handled errors/supported ANRs; qualify Firebase Performance, release resource probes and app/process identity | Android Studio/Perfetto/simpleperf, heap dump/LeakCanary, package/asset analysis |
| iOS | DevTools observations in debug builds; Crashlytics crashes/handled errors; qualify Firebase Performance, startup/frame probes and physical-footprint measurements | Instruments allocations/leaks/time profiler; symbols and device crash diagnostics |
| Browser | Navigation/resource/error observations through Reaktor's own client evidence and versioned bundles | Performance recording, allocation/heap snapshots, detached DOM and listener analysis |
| Worker / Durable Object | Provider invocation CPU/duration/errors, limits and resource identifiers | Supported local/deployed runtime captures; application state/resource-growth evidence. PID/heap fields may be unavailable |
| Native / FFI | Host process and owned allocation/resource counters | Supported native profiler, sanitizers and allocator evidence on qualified builds |
Android distinguishes process memory measures and memory-pressure behavior in its memory guide. Collectors must retain which measure they actually report.
Crashlytics does not supply a resource timeline or prove a retained-object leak. Qualify existing Android memory and iOS physical-footprint probes by SDK, build and device; use the platform profilers for deeper attribution. Firebase Performance is a separate integration. Missing measurements remain visible in the required-probe manifest rather than becoming zero usage or a green result.
Proving a leak
- Pin artifact, device/runtime, flags, workload and initial state. Warm caches separately, then repeat a bounded lifecycle such as open/send/close, graph attach/detach or live update.
- Measure the idle baseline, peaks and return after quiescence. Account for cache policy, GC timing and retained pools. Increasing RSS alone is a suspicion, not a leak diagnosis.
- Compare equivalent post-GC live sets or retained ownership evidence. Use heap dominators/paths to roots for managed memory, native allocation evidence for native growth, and resource counts for non-memory leaks.
- Identify the retained owner: listener, scope, coroutine/job, timer, classloader, native handle, direct buffer or cache. Link it to a graph lifecycle when that attribution is supported.
- Reproduce the growth on baseline/candidate in isolated Shadow workspaces. Verify both bounded growth and disposal; retain dumps/profiles plus the assertion and capture interval.
Heap and memory artifacts may contain sensitive data and are expensive to collect. Record capture impact and access policy. Oracle's leak troubleshooting guide distinguishes Java-heap and native investigations; the profiling page turns this into a JVM workflow.
Budgets and workbench behavior
A required-measurement manifest names target/revision, metric, unit, collector and acceptance rule. Use absolute limits and baseline-relative deltas where appropriate; product/device owners choose limits from evidence. Outcomes are passed, exceeded, no collector and measurement failed. A skipped probe cannot produce green.
Show count and coverage: for example, ready replicas versus desired, observed processes versus expected, and sessions measured versus eligible. Join peaks and restarts to deploys and user journeys. Keep original artifacts reachable from findings and preserve identity and attribution limits.