docs: record that the core runs without the UI, and the CPU cost of the UI
States where run data lives now that Iperf3Session owns it, so the next person does not put accumulation back in the view model, and documents the headless entry point as the way to check that claim rather than trust it. Includes the measurement that motivates using it: 30.2% local CPU headless versus 79.9% through the UI on a comparable 4-stream run. That gap is worth recording, because it means throughput read off the app's own screen is pessimistic at high rates and should not be compared against a headless or desktop figure without noting which path produced it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+24
-1
@@ -7,11 +7,13 @@ A Flutter-based Android GUI wrapper for iperf3, the popular network performance
|
||||
```
|
||||
lib/ # Flutter/Dart application layer
|
||||
├── main.dart # Composition root: picks the Iperf3Runner impl
|
||||
├── main_headless.dart # Runs a test with no widgets (see Layering)
|
||||
├── domain/ # Pure Dart — no Flutter import
|
||||
│ ├── models/
|
||||
│ │ ├── test_configuration.dart # Server, port, duration, interval, parallel streams
|
||||
│ │ ├── iperf3_result.dart # Raw output, exit code, stopped flag
|
||||
│ │ └── iperf3_event.dart # Parsed --json-stream reports
|
||||
│ │ ├── iperf3_event.dart # Parsed --json-stream reports
|
||||
│ │ └── iperf3_session.dart # One run accumulated: samples, totals, stats
|
||||
│ └── services/
|
||||
│ └── iperf3_runner.dart # The contract the UI depends on
|
||||
├── data/ # Transport — flutter/services only
|
||||
@@ -69,6 +71,27 @@ tree against an in-memory runner with no MethodChannel, native library or
|
||||
device — and what keeps a test double at five stable members instead of
|
||||
mirroring the transport's whole surface.
|
||||
|
||||
**The core does not need the UI.** What happened during a run is accumulated by
|
||||
`Iperf3Session` in the domain layer — samples, totals, errors, and the mean,
|
||||
peak and retransmit figures over them. The view model holds no run data of its
|
||||
own and the screen derives no numbers; both read the session. Replacing the
|
||||
presentation layer therefore means rewriting rendering, not re-deriving results.
|
||||
|
||||
`lib/main_headless.dart` is the standing proof: it runs a full test through
|
||||
`Iperf3Service` and `Iperf3Session` with `WidgetsFlutterBinding` but no
|
||||
`runApp` — no widget tree, no render surface. If the run path ever starts
|
||||
needing the UI, it stops working.
|
||||
|
||||
```bash
|
||||
flutter run -t lib/main_headless.dart \
|
||||
--dart-define=IPERF_SERVER=192.168.2.182 --dart-define=IPERF_STREAMS=4
|
||||
```
|
||||
|
||||
Use it when a figure has to be trustworthy. A 4-stream local run reports
|
||||
**30.2% local CPU headless against 79.9% through the UI** — the phone is near
|
||||
CPU-bound at gigabit rates, so a repainting transcript measurably depresses
|
||||
throughput. Numbers taken through the UI are pessimistic.
|
||||
|
||||
`test/architecture_test.dart` enforces all of this by reading the actual
|
||||
imports under `lib/`, including a check that no fourth layer directory has
|
||||
appeared unnoticed. Change the layering there when the layering should change;
|
||||
|
||||
Reference in New Issue
Block a user