Why `dart analyze` Is the Real Bottleneck in AI-Assisted Flutter Development
For AI-driven development on large Dart/Flutter codebases, the analyzer startup cost is the real bottleneck in the modify-verify-fix loop. Making the analyzer a long-lived service brings verification time down to interactive speeds and keeps parallel worktrees from exhausting memory.
AI-assisted coding turns static analysis into a high-frequency feedback step. Each time an AI edits a few lines, `dart analyze` reruns. On large Flutter projects with 15,000 files, that means paying full analyzer startup cost every iteration: spawning a process, initializing analysis context, loading plugins. The command-line tool `dana` solves this by making the analyzer a persistent daemon. First check warms the session; subsequent checks send incremental requests. In a benchmark monorepo, a single-file check dropped from about 3 minutes with a cold `dart analyze` to 0.5 seconds with a warmed session. Directory and full-project checks also fall to about a second.
The tool also addresses parallel AI tasks. When several Git worktrees each run their own analyzer, memory blows up. `dana` supports an opt-in multi-root pool: with `DANA_MULTI_ROOT=1`, compatible worktrees share one analyzer process, keeping separate analysis contexts but sharing the Dart runtime and some global caches. Windows tests with two synthetic worktrees showed analyzer job private commit drops from 2,464 MiB to 1,435 MiB, about 41.8%, with negligible latency increase (hot single-file p50 rose 0.58 ms). The pool has safeguards: a max root count (default 3), LRU eviction, memory admission checks that fail with exit code 75 rather than spawning another analyzer, and idle root reclamation under memory pressure. On macOS, only `critical` pressure triggers pool reclamation; `warn` is treated as a hint.
`dana` is part of the `dart_analysis_daemon` package on pub.dev, and a companion `dart_analysis_server_proxy` lets the command line reuse an IDE's already-running analyzer. The multi-root pool is deliberately opt-in to avoid changing behavior for users who don't need it. The author's key point: persistence beats narrowing scope. Repeatedly starting a fresh analyzer is the cost that hurts AI loops, not the per-file analysis itself.
Persistence outperforms narrower scope: in the benchmark, reusing a warm analyzer saved far more time than pointing `dart analyze` at a single file, because startup dominates the cost.
The deliberate opt-in for multi-root sharing means memory benefits only appear when users set the flag, but it avoids silently changing the analyzer's process model for everyone.
Treating the analyzer as a long-lived service rather than a per-command tool reframes the economics of AI verification; cheap checks make the AI edit-verify-fix loop viable on large codebases.
Nice, with a slightly weaker computer analyzing a file once is very time-consuming. I'll try it out when I have time.