Radar Desktop · macOS-first

Everything the suite captures — on your desktop.

Import heap dumps and Perfetto traces for fully offline analysis, attach to a running app's Dart VM Service for a live connected mode, or capture Android native-heap allocations over adb. One macOS-first app, dump-first, connection optional.

Offline .dartheap / .pftrace
Connected ws:// VM Service
Android Native adb + heapprofd

Three modes, one app.

pick up wherever you are

Offline · no connection needed

Dump-first. Everything works without a running app.

Drop in a .dartheap snapshot or a Perfetto .pftrace capture and the full memory-analysis workflow is available immediately — the same analysis the DevTools companion offers, built for keeping many captures side by side across a long soak test.

A workspace of dumps

Every imported dump in one place — file or capture, size, class count, retained bytes. Pick up exactly where you left off.

Class histogram

Per-class instance counts and shallow bytes for a single dump, sortable and searchable, tagged by dominant root kind.

Retaining paths

Grouped by dominant root kind, with the full gc-root → field → … → object hop list on drill-down.

Compare & diff

Pick two dumps and rank per-class growth by instances and bytes — the same diff the DevTools companion does, on desktop.

Trends

Plot one class's instance or byte count across every dump in the workspace — the tool for a class that never returns to baseline.

Connected · optional

Attach to a running app. More appears — nothing switches off.

Point Radar Desktop at the ws:// URI flutter run prints and it attaches to that app's Dart VM Service. Offline analysis keeps working exactly as before; connecting only adds capability.

Live heap capture

Capture a snapshot straight from the attached app into the workspace — identical downstream analysis to an imported dump. Force GC first.

Performance, live

Traces (count, avg, p95/p99, total, rate) and frame/jank timing — the same tables the DevTools companion and on-device inspector show.

Stability, live

Uncaught errors with repeat counts, and main-thread stalls correlated to the trace that blocked the isolate.

Honest when it can't see something.

Live Performance and Stability need the target app to embed the Radar runtime. Attach to a plain Flutter app instead, and those tabs report a clear "not detected" state — never a fabricated reading.

no runtime → not detected never a guessed number

Android native profiling

The memory below the Dart heap.

Capture native-heap allocations from a device via adb + heapprofd + Perfetto, then work with the trace entirely on desktop — per-module still-live analysis, checkpoint compare/diff, and an FFI-allocations lane for blocks tied to a real Dart file:line.

  • Ranked by module — app, plugin, engine, GPU driver
  • Checkpoint compare: added / grew / shrank / gone
  • FFI-allocations lane, grouped by Dart call site, once a log is imported
  • Native symbolization via build-id-matched .so files
  • Guided on-device capture over adb (profile/release builds)
libapp.so · app
└─ ImageDecoderCache::alloc still-live 4.2 MB · Δ +1.1 MB
libwebrtc.so · plugin
└─ module-only still-live 2.8 MB · add symbols to resolve

Get it running

One Flutter app, no separate install.

Radar Desktop lives in this repo as a Flutter desktop app, built on the shared radar_workbench analysis engine and the radar_ui design system — the same two foundations behind the DevTools companion.

View packages/radar_desktop
packages/radar_desktoprun
flutter run -d macos
packages/radar_desktopbuild
flutter build macos

An app, not a pub.dev package.

Radar Desktop ships as a Flutter desktop app (publish_to: none), not a dependency you add to a project. Android profiling and native symbolization shell out to a few external tools; each is auto-detected, and without one, the feature it powers reports a clear "not available" state instead of guessing.

auto-detected trace_processor llvm-symbolizer llvm-readelf adb